diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..8a66f3a --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,78 @@ +# Copyright (c) 2024-2026 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. + +# GitHub Actions workflow to lint, build and test. +name: "Go" +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +concurrency: + group: "go-${{ github.workflow }}-${{ github.event.number || github.ref }}" + cancel-in-progress: "${{ github.event_name == 'pull_request' }}" + +env: + # renovate: datasource=github-releases depName=golangci/golangci-lint versioning=semver + GOLANGCI_LINT_VERSION: "v2.11.3" + +permissions: + contents: read + +jobs: + test: + name: "Test" + runs-on: "ubuntu-latest" + timeout-minutes: 150 + strategy: + fail-fast: false # if one of these fails, still run the others + matrix: + module: + - eth-trie + - merkle + - tss-lib + steps: + - name: "Checkout repository" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: "Setup Go" + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + with: + go-version-file: "${{ matrix.module }}/go.mod" + + - name: "go get" + working-directory: ${{ matrix.module }} + run: go mod download && go mod verify + + - name: "go test" + working-directory: ${{ matrix.module }} + run: go test -tags tssexamples -timeout 120m -v -cover ./... + + lint: + name: "Lint" + runs-on: "ubuntu-latest" + strategy: + fail-fast: false + matrix: + module: + - tss-lib + steps: + - name: "Checkout repository" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: "Setup Go" + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + with: + go-version-file: "${{ matrix.module }}/go.mod" + + - name: "golangci-lint" + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 + with: + working-directory: "${{ matrix.module }}" + version: "${{ env.GOLANGCI_LINT_VERSION }}" + + - name: "golangci-lint fmt" + working-directory: "${{ matrix.module }}" + run: golangci-lint fmt --diff ./... diff --git a/eth-trie/trie_test.go b/eth-trie/trie_test.go index 3cb2b19..c27f986 100644 --- a/eth-trie/trie_test.go +++ b/eth-trie/trie_test.go @@ -25,13 +25,15 @@ import ( "github.com/hemilabs/x/eth-trie/triedb/pathdb" ) +// TestZKTrie is a basic example of how one could use the eth-trie for +// alternative data storage. It is a prototype for ZKTrie. func TestZKTrie(t *testing.T) { const ( - blockCount uint64 = 1000000 // num of blocks + blockCount uint64 = 10 // num of blocks // newOutsCount >= inCount + outCount - newOutsCount uint64 = 1500 // num of outs with new scripts - inCount uint64 = 1000 // num of ins - outCount uint64 = 500 // num of outs with previous scripts + newOutsCount uint64 = 10 // num of outs with new scripts + inCount uint64 = 0 // num of ins + outCount uint64 = 0 // num of outs with previous scripts ) datadir := t.TempDir() diff --git a/tss-lib/.gitignore b/tss-lib/.gitignore new file mode 100644 index 0000000..965ecd6 --- /dev/null +++ b/tss-lib/.gitignore @@ -0,0 +1,6 @@ +bin/ +.gocache/ +pkg/ +coverage.out +test.log +*.swp diff --git a/tss-lib/.golangci.yaml b/tss-lib/.golangci.yaml new file mode 100644 index 0000000..07dce51 --- /dev/null +++ b/tss-lib/.golangci.yaml @@ -0,0 +1,74 @@ +version: "2" +run: + tests: true + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - "asasalint" # Check for pass []any as any in variadic func(...any). + - "dupword" # Checks for duplicate words in the source code. + - "errcheck" # Checks for unchecked errors. + - "errorlint" # Verifies errors are properly wrapped. + - "errname" # Checks that sentinel errors are prefixed with the Err. + - "gocheckcompilerdirectives" # Checks that go compiler directives are valid. + - "gochecksumtype" # Run exhaustiveness checks on Go "sum types". + - "gomoddirectives" # Manages 'replace', 'retract' and 'excludes' directives. + - "gosmopolitan" # Report certain i18n/l10n anti-patterns. + - "govet" # Runs go vet. + - "ineffassign" # Detects when assignments to variables are not used. + - "makezero" # Finds slice declarations with non-zero initial length. + - "misspell" # Finds common typing mistakes. + - "nilerr" # Finds code that returns nil even if it checks error is not nil. + - "nolintlint" # Reports ill-formed or insufficient nolint directives. + - "prealloc" # Finds slice declarations that could be pre-allocated. + - "predeclared" # Find code that shadows predeclared identifiers. + - "staticcheck" # Runs staticcheck. + - "unconvert" # Checks for unnecessary type conversions. + - "usestdlibvars" # Detects the possibility to use stdlib vars/constants. + - "usetesting" # Reports use of functions with replacements in testing. + - "unused" # Checks for unused constants, variables, functions, types. + - "whitespace" # Checks for unnecessary newlines. + settings: + gomoddirectives: + replace-local: true # tss-lib fork not yet pushed. + nolintlint: + require-explanation: true + exclusions: + generated: "strict" + presets: + - "comments" + - "common-false-positives" + - "legacy" + - "std-error-handling" + rules: + - linters: [ "staticcheck" ] + text: "QF1001:" # "could apply De Morgan's law" + - linters: [ "staticcheck" ] + text: "QF1007:" # "could merge conditional assignment" + - linters: [ "staticcheck" ] + text: "SA1019:.*elliptic\\." # tss-lib requires raw curve arithmetic (Add, ScalarMult, etc.) + - linters: [ "staticcheck" ] + text: "SA1019:.*\\.Add has been deprecated" # elliptic.Curve.Add + - linters: [ "staticcheck" ] + text: "SA1019:.*\\.ScalarMult has been deprecated" # elliptic.Curve.ScalarMult + - linters: [ "staticcheck" ] + text: "SA1019:.*\\.ScalarBaseMult has been deprecated" # elliptic.Curve.ScalarBaseMult + - linters: [ "staticcheck" ] + text: "SA1019:.*\\.IsOnCurve has been deprecated" # elliptic.Curve.IsOnCurve + +formatters: + enable: + - "gci" # Enforces package import order. + - "gofumpt" # Extended go fmt. + settings: + gci: + sections: + - "standard" + - "default" + - "blank" + - "dot" + - "localmodule" + custom-order: true diff --git a/tss-lib/LICENSE b/tss-lib/LICENSE index 03b6589..3a9750a 100644 --- a/tss-lib/LICENSE +++ b/tss-lib/LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2019 Binance +Copyright (c) 2026 Hemi Labs, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/tss-lib/Makefile b/tss-lib/Makefile index 4ffff95..8dcddeb 100644 --- a/tss-lib/Makefile +++ b/tss-lib/Makefile @@ -1,48 +1,64 @@ -MODULE = github.com/bnb-chain/tss-lib/v2 -PACKAGES = $(shell go list ./... | grep -v '/vendor/') +# Copyright (c) 2026 Hemi Labs, Inc. +# Use of this source code is governed by the MIT License, +# which can be found in the LICENSE file. -all: protob test +PROJECTPATH = $(abspath $(dir $(realpath $(firstword $(MAKEFILE_LIST))))) -######################################## -### Protocol Buffers +export GOBIN=$(PROJECTPATH)/bin +export GOCACHE=$(PROJECTPATH)/.gocache +export GOPKG=$(PROJECTPATH)/pkg -protob: - @echo "--> Building Protocol Buffers" - @for protocol in message signature ecdsa-keygen ecdsa-signing ecdsa-resharing eddsa-keygen eddsa-signing eddsa-resharing; do \ - echo "Generating $$protocol.pb.go" ; \ - protoc --go_out=. ./protob/$$protocol.proto ; \ - done +# renovate: datasource=github-releases depName=golangci/golangci-lint versioning=semver +GOLANGCI_LINT_VERSION="v2.11.3" +# renovate: datasource=github-releases depName=joshuasing/golicenser versioning=semver +GOLICENSER_VERSION="v0.3.1" +# renovate: datasource=github-releases depName=mvdan/gofumpt versioning=semver +GOFUMPT_VERSION="v0.9.2" -build: protob - go fmt ./... +cmds = \ + tss-ecdsa-demo \ + tss-eddsa-demo \ -######################################## -### Testing +.PHONY: all clean deps go-deps $(cmds) build lint lint-deps tidy race test vulncheck vulncheck-deps -test_unit: - @echo "--> Running Unit Tests" - @echo "!!! WARNING: This will take a long time :)" - go clean -testcache - go test -timeout 60m $(PACKAGES) +all: tidy build lint test -test_unit_race: - @echo "--> Running Unit Tests (with Race Detection)" - @echo "!!! WARNING: This will take a long time :)" - go clean -testcache - go test -timeout 60m -race $(PACKAGES) +clean: + rm -rf $(GOBIN) $(GOCACHE) $(GOPKG) -test: - make test_unit +deps: lint-deps vulncheck-deps go-deps + +go-deps: + go mod download + go mod tidy + go mod verify + +$(cmds): + go build -trimpath -ldflags "$(GO_LDFLAGS)" -o $(GOBIN)/$@ ./cmd/$@ + +build: + go build ./... -######################################## -### Pre Commit +lint: + $(shell go env GOPATH)/bin/golangci-lint fmt ./... + $(shell go env GOPATH)/bin/golangci-lint run --fix ./... -pre_commit: build test +lint-deps: + @echo "Installing with $(shell go env GOVERSION)" + GOBIN=$(shell go env GOPATH)/bin go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) + GOBIN=$(shell go env GOPATH)/bin go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) -######################################## +tidy: + go mod tidy + +race: + go test -v -race -timeout 60m ./... + +test: + go test -timeout 30m -coverprofile=$(PROJECTPATH)/coverage.out -covermode=atomic ./... -# To avoid unintended conflicts with file names, always add to .PHONY -# # unless there is a reason not to. -# # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: protob build test_unit test_unit_race test +vulncheck: + $(shell go env GOPATH)/bin/govulncheck ./... +vulncheck-deps: + GOBIN=$(shell go env GOPATH)/bin go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/tss-lib/README.md b/tss-lib/README.md index c4411d9..c852b3a 100644 --- a/tss-lib/README.md +++ b/tss-lib/README.md @@ -1,162 +1,230 @@ -# Multi-Party Threshold Signature Scheme -[![MIT licensed][1]][2] [![GoDoc][3]][4] [![Go Report Card][5]][6] +# Hemi TSS Library (v3) -[1]: https://img.shields.io/badge/license-MIT-blue.svg -[2]: LICENSE -[3]: https://godoc.org/github.com/bnb-chain/tss-lib?status.svg -[4]: https://godoc.org/github.com/bnb-chain/tss-lib -[5]: https://goreportcard.com/badge/github.com/bnb-chain/tss-lib -[6]: https://goreportcard.com/report/github.com/bnb-chain/tss-lib +[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -Permissively MIT Licensed. +Threshold signature scheme library for ECDSA (secp256k1) and EdDSA +(Ed25519), forked from [binance/tss-lib](https://github.com/bnb-chain/tss-lib) +with security audit fixes and a channel-free round function API. -Note! This is a library for developers. You may find a TSS tool that you can use with the Binance Chain CLI [here](https://docs.binance.org/tss.html). +## Attribution -## Introduction -This is an implementation of multi-party {t,n}-threshold ECDSA (Elliptic Curve Digital Signature Algorithm) based on Gennaro and Goldfeder CCS 2018 [1] and EdDSA (Edwards-curve Digital Signature Algorithm) following a similar approach. +This library is built on the excellent work of the +[Binance tss-lib](https://github.com/bnb-chain/tss-lib) team, which +provided a solid, well-structured implementation of GG18/GG20 +threshold ECDSA and EdDSA. The original Feldman VSS, Paillier +encryption, Schnorr proofs, and MtA protocol implementations form the +cryptographic foundation of this library. We are grateful for their +contribution to the open-source TSS ecosystem. -This library includes three protocols: +Our fork (v3) adds security audit fixes, removes protobuf in favor of +plain Go structs, replaces the channel-based state machine with pure +round functions, and adds overlapping-committee resharing support. +See [SECURITY_FIXES.md](SECURITY_FIXES.md) for details on the audit +fixes. -* Key Generation for creating secret shares with no trusted dealer ("keygen"). -* Signing for using the secret shares to generate a signature ("signing"). -* Dynamic Groups to change the group of participants while keeping the secret ("resharing"). +## v3 API -⚠️ Do not miss [these important notes](#how-to-use-this-securely) on implementing this library securely +v3 replaces the channel-based `Party`/`Round`/`BaseUpdate` state +machine with pure round functions. Each round takes explicit state + +inbound messages and returns outbound messages. The caller owns the +event loop. -## Rationale -ECDSA is used extensively for crypto-currencies such as Bitcoin, Ethereum (secp256k1 curve), NEO (NIST P-256 curve) and many more. +**No protobuf.** All message types are plain Go structs with typed +fields. Serialization is the caller's responsibility — the library +does not prescribe a wire format. -EdDSA is used extensively for crypto-currencies such as Cardano, Aeternity, Stellar Lumens and many more. +## ECDSA — Keygen / Sign / Reshare -For such currencies this technique may be used to create crypto wallets where multiple parties must collaborate to sign transactions. See [MultiSig Use Cases](https://en.bitcoin.it/wiki/Multisignature#Multisignature_Applications) +Complete runnable example: [`ecdsa/example_test.go`](ecdsa/example_test.go) -One secret share per key/address is stored locally by each participant and these are kept safe by the protocol – they are never revealed to others at any time. Moreover, there is no trusted dealer of the shares. +``` +go test -tags tssexamples -v -run TestECDSAKeygenSignReshare ./ecdsa/ -timeout 15m +``` + +### Keygen (4 rounds) -In contrast to MultiSig solutions, transactions produced by TSS preserve the privacy of the signers by not revealing which `t+1` participants were involved in their signing. +```go +import "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" -There is also a performance bonus in that blockchain nodes may check the validity of a signature without any extra MultiSig logic or processing. +// Generate Paillier pre-params (CPU-intensive, do out-of-band). +preParams, _ := keygen.GeneratePreParams(5 * time.Minute) -## Usage -You should start by creating an instance of a `LocalParty` and giving it the arguments that it needs. +params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) +state, r1out, _ := keygen.Round1(ctx, params, *preParams) +r2out, _ := keygen.Round2(ctx, state, r1Msgs) +r3out, _ := keygen.Round3(ctx, state, r2p2p, r2bcast) +r4out, _ := keygen.Round4(ctx, state, r3Msgs) +// r4out.Save = LocalPartySaveData (key share) +``` -The `LocalParty` that you use should be from the `keygen`, `signing` or `resharing` package depending on what you want to do. +### Signing (9 rounds + finalize) -### Setup ```go -// When using the keygen party it is recommended that you pre-compute the "safe primes" and Paillier secret beforehand because this can take some time. -// This code will generate those parameters using a concurrency limit equal to the number of available CPU cores. -preParams, _ := keygen.GeneratePreParams(1 * time.Minute) - -// Create a `*PartyID` for each participating peer on the network (you should call `tss.NewPartyID` for each one) -parties := tss.SortPartyIDs(getParticipantPartyIDs()) - -// Set up the parameters -// Note: The `id` and `moniker` fields are for convenience to allow you to easily track participants. -// The `id` should be a unique string representing this party in the network and `moniker` can be anything (even left blank). -// The `uniqueKey` is a unique identifying key for this peer (such as its p2p public key) as a big.Int. -thisParty := tss.NewPartyID(id, moniker, uniqueKey) -ctx := tss.NewPeerContext(parties) - -// Select an elliptic curve -// use ECDSA -curve := tss.S256() -// or use EdDSA -// curve := tss.Edwards() - -params := tss.NewParameters(curve, ctx, thisParty, len(parties), threshold) - -// You should keep a local mapping of `id` strings to `*PartyID` instances so that an incoming message can have its origin party's `*PartyID` recovered for passing to `UpdateFromBytes` (see below) -partyIDMap := make(map[string]*PartyID) -for _, id := range parties { - partyIDMap[id.Id] = id -} +import "github.com/hemilabs/x/tss-lib/v3/ecdsa/signing" + +m := new(big.Int).SetBytes(msgHash[:]) +sigState, r1out, _ := signing.SignRound1(params, keyShare, m, nil, 0) +r2out, _ := signing.SignRound2(ctx, sigState, r1p2p, r1bcast) +r3out, _ := signing.SignRound3(ctx, sigState, r2p2p) +// Rounds 4-9 are all broadcast: +r4out, _ := signing.SignRound4(sigState, r3) +r5out, _ := signing.SignRound5(sigState, r4) +r6out, _ := signing.SignRound6(sigState) +r7out, _ := signing.SignRound7(sigState, r5, r6) +r8out, _ := signing.SignRound8(sigState) +r9out, _ := signing.SignRound9(sigState, r7, r8) +finalOut, _ := signing.SignFinalize(sigState, r9) +// finalOut.Signature.R, .S = standard ECDSA sig ``` -### Keygen -Use the `keygen.LocalParty` for the keygen protocol. The save data you receive through the `endCh` upon completion of the protocol should be persisted to secure storage. +### Resharing (5 rounds, overlapping committees) ```go -party := keygen.NewLocalParty(params, outCh, endCh, preParams) // Omit the last arg to compute the pre-params in round 1 -go func() { - err := party.Start() - // handle err ... -}() +import "github.com/hemilabs/x/tss-lib/v3/ecdsa/resharing" + +// Supports overlapping committees: [P0,P1,P2] → [P1,P2,P3] +// Each committee needs its own *PartyID copies (SortPartyIDs +// mutates Index). +params := tss.NewReSharingParameters( + tss.S256(), oldCtx, newCtx, myPID, + oldN, oldT, newN, newT) + +state, r1out, _ := resharing.ReshareRound1(params, keyShare, newPreParams) +r2out, _ := resharing.ReshareRound2(state, r1Msgs) +r3out, _ := resharing.ReshareRound3(state, r2AckMsgs) +r4out, _ := resharing.ReshareRound4(ctx, state, r2Msgs, r3p2p, r3bcast) +r5out, _ := resharing.ReshareRound5(state, r4p2p, r4bcast) +// r5out.Save = new key share (new committee), old Xi zeroed ``` -### Signing -Use the `signing.LocalParty` for signing and provide it with a `message` to sign. It requires the key data obtained from the keygen protocol. The signature will be sent through the `endCh` once completed. +## EdDSA — Keygen / Sign / Reshare -Please note that `t+1` signers are required to sign a message and for optimal usage no more than this should be involved. Each signer should have the same view of who the `t+1` signers are. +Complete runnable example: [`eddsa/example_test.go`](eddsa/example_test.go) -```go -party := signing.NewLocalParty(message, params, ourKeyData, outCh, endCh) -go func() { - err := party.Start() - // handle err ... -}() +``` +go test -tags tssexamples -v -run TestEdDSAKeygenSignReshare ./eddsa/ -timeout 5m ``` -### Re-Sharing -Use the `resharing.LocalParty` to re-distribute the secret shares. The save data received through the `endCh` should overwrite the existing key data in storage, or write new data if the party is receiving a new share. +EdDSA is simpler than ECDSA: no Paillier pre-parameters, no MtA. +Keygen is 3 rounds (vs 4), signing is 3+finalize (vs 9+finalize). -Please note that `ReSharingParameters` is used to give this Party more context about the re-sharing that should be carried out. +### Keygen (3 rounds) ```go -party := resharing.NewLocalParty(params, ourKeyData, outCh, endCh) -go func() { - err := party.Start() - // handle err ... -}() +import "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + +// No pre-parameters needed for EdDSA. +params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) +state, r1out, _ := keygen.Round1(params) +r2out, _ := keygen.Round2(state, r1Msgs) +r3out, _ := keygen.Round3(state, r2p2p, r2bcast) +// r3out.Save = LocalPartySaveData (key share) ``` -⚠️ During re-sharing the key data may be modified during the rounds. Do not ever overwrite any data saved on disk until the final struct has been received through the `end` channel. +### Signing (3 rounds + finalize) -## Messaging -In these examples the `outCh` will collect outgoing messages from the party and the `endCh` will receive save data or a signature when the protocol is complete. +```go +import "github.com/hemilabs/x/tss-lib/v3/eddsa/signing" + +m := new(big.Int).SetBytes(msgHash[:]) +sigState, r1out, _ := signing.SignRound1(params, keyShare, m, 0) +r2out, _ := signing.SignRound2(sigState, r1) +r3out, _ := signing.SignRound3(sigState, r2) +finalOut, _ := signing.SignFinalize(sigState, r3) +// finalOut.Signature.R, .S = standard EdDSA sig +// finalOut.Signature.Signature = 64-byte R||S encoding +``` -During the protocol you should provide the party with updates received from other participating parties on the network. +### Resharing (5 rounds, overlapping committees) -A `Party` has two thread-safe methods on it for receiving updates. ```go -// The main entry point when updating a party's state from the wire -UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (ok bool, err *tss.Error) -// You may use this entry point to update a party's state when running locally or in tests -Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) +import "github.com/hemilabs/x/tss-lib/v3/eddsa/resharing" + +// Same dual-committee pattern as ECDSA, but no Paillier. +params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, myPID, + oldN, oldT, newN, newT) + +state, r1out, _ := resharing.ReshareRound1(params, &keyShare) +r2out, _ := resharing.ReshareRound2(state, r1Msgs) +r3out, _ := resharing.ReshareRound3(state, r2AckMsgs) +r4out, _ := resharing.ReshareRound4(state, r1Msgs, r3p2p, r3bcast) +r5out, _ := resharing.ReshareRound5(state, r4AckMsgs) +// r5out.Save = new key share (new committee), old Xi zeroed ``` -And a `tss.Message` has the following two methods for converting messages to data for the wire: +## Message Routing + +Round functions return `[]*tss.Message`. Each message has: + +- `msg.From` — sender's `*tss.PartyID` +- `msg.To` — `[]*tss.PartyID` (nil = broadcast to all) +- `msg.IsBroadcast` — redundant flag for convenience +- `msg.Content` — `interface{}` holding the round-specific struct + +The caller is responsible for serializing `Content` and delivering +it to the correct parties. See the heminetwork continuum service +for a JSON-based wire format example. + +## Overlapping Committees + +When resharing between committees that share members (e.g., +`[P0,P1,P2] → [P1,P2,P3]`), each committee **must** have its own +`*PartyID` copies: + ```go -// Returns the encoded message bytes to send over the wire along with routing information -WireBytes() ([]byte, *tss.MessageRouting, error) -// Returns the protobuf wrapper message struct, used only in some exceptional scenarios (i.e. mobile apps) -WireMsg() *tss.MessageWrapper +copyPID := func(src *tss.PartyID) *tss.PartyID { + return tss.NewPartyID(src.Id, src.Moniker, + new(big.Int).SetBytes(src.Key)) +} ``` -In a typical use case, it is expected that a transport implementation will consume message bytes via the `out` channel of the local `Party`, send them to the destination(s) specified in the result of `msg.GetTo()`, and pass them to `UpdateFromBytes` on the receiving end. - -This way there is no need to deal with Marshal/Unmarshalling Protocol Buffers to implement a transport. +`SortPartyIDs` assigns `Index` by sort position within the committee. +Shared `*PartyID` objects would have their Index overwritten by the +second sort. -## Changes of Preparams of ECDSA in v2.0 +## Security Audit -Two fields PaillierSK.P and PaillierSK.Q is added in version 2.0. They are used to generate Paillier key proofs. Key valuts generated from versions before 2.0 need to regenerate(resharing) the key valuts to update the praparams with the necessary fileds filled. +See [SECURITY_FIXES.md](SECURITY_FIXES.md) for the complete list of +security fixes from the v2 audit (76 in v3 production code, annotated +with `[FORK]` comments). -## How to use this securely +## Packages -⚠️ This section is important. Be sure to read it! +| Package | Description | +|---------|-------------| +| `ecdsa/keygen` | ECDSA distributed key generation (4 rounds) | +| `ecdsa/signing` | ECDSA threshold signing (9 rounds + finalize) | +| `ecdsa/resharing` | ECDSA key resharing (5 rounds, dual committee) | +| `eddsa/keygen` | EdDSA distributed key generation (3 rounds) | +| `eddsa/signing` | EdDSA threshold signing (3 rounds + finalize) | +| `eddsa/resharing` | EdDSA key resharing (5 rounds, dual committee) | +| `tss` | Core types: Parameters, PartyID, Message | +| `common` | Hash utilities, safe prime generation, random | +| `crypto` | EC points, Paillier, VSS, ZK proofs, commitments | -The transport for messaging is left to the application layer and is not provided by this library. Each one of the following paragraphs should be read and followed carefully as it is crucial that you implement a secure transport to ensure safety of the protocol. +## Running the Demos -When you build a transport, it should offer a broadcast channel as well as point-to-point channels connecting every pair of parties. Your transport should also employ suitable end-to-end encryption (TLS with an [AEAD cipher](https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data_(AEAD)) is recommended) between parties to ensure that a party can only read the messages sent to it. +Standalone CLI programs that run the full lifecycle: +keygen → sign → reshare (overlapping committees) → sign. -Within your transport, each message should be wrapped with a **session ID** that is unique to a single run of the keygen, signing or re-sharing rounds. This session ID should be agreed upon out-of-band and known only by the participating parties before the rounds begin. Upon receiving any message, your program should make sure that the received session ID matches the one that was agreed upon at the start. +``` +# EdDSA (fast — no Paillier, ~1 second): +go run ./cmd/tss-eddsa-demo -Additionally, there should be a mechanism in your transport to allow for "reliable broadcasts", meaning parties can broadcast a message to other parties such that it's guaranteed that each one receives the same message. There are several examples of algorithms online that do this by sharing and comparing hashes of received messages. +# ECDSA (slow — Paillier safe-prime generation, ~30 seconds): +go run ./cmd/tss-ecdsa-demo +``` -Timeouts and errors should be handled by your application. The method `WaitingFor` may be called on a `Party` to get the set of other parties that it is still waiting for messages from. You may also get the set of culprit parties that caused an error from a `*tss.Error`. +## Testing -## Security Audit -A full review of this library was carried out by Kudelski Security and their final report was made available in October, 2019. A copy of this report [`audit-binance-tss-lib-final-20191018.pdf`](https://github.com/bnb-chain/tss-lib/releases/download/v1.0.0/audit-binance-tss-lib-final-20191018.pdf) may be found in the v1.0.0 release notes of this repository. +``` +make test # all tests +make lint # golangci-lint +make race # race detector +make vulncheck # govulncheck +``` -## References -\[1\] https://eprint.iacr.org/2019/114.pdf +## License +MIT — see [LICENSE](LICENSE). diff --git a/tss-lib/SECURITY.md b/tss-lib/SECURITY.md deleted file mode 100644 index e8641a6..0000000 --- a/tss-lib/SECURITY.md +++ /dev/null @@ -1,11 +0,0 @@ -# Security Policy - -## Reporting a Bug or Vulnerability - -For non-security problems please open an issue in this GitHub repository. - -If you find any security issues please send a report confidentially to https://bugbounty.bnbchain.org/. - -Please include notes about the impact of the issue and a walkthrough on how it can be exploited. - -For severe security issues that completely breach the safety of the scheme or leak the secret shares we would be happy to reward you with a bounty based on the security impact and severity. Please include a link to this notice in your email. diff --git a/tss-lib/SECURITY_FIXES.md b/tss-lib/SECURITY_FIXES.md new file mode 100644 index 0000000..aa00853 --- /dev/null +++ b/tss-lib/SECURITY_FIXES.md @@ -0,0 +1,205 @@ +# Security Fixes — v2 Audit → v3 Implementation + +Security fixes from the audit of upstream +[binance/tss-lib](https://github.com/bnb-chain/tss-lib), implemented +in the v3 channel-free round function architecture. + +76 fixes in production code across 24 files, all annotated with +`[FORK]` comments in source. Grep for `[FORK]` to find them all. + +The v2 base had 260 annotations across 88 files — the difference is +that v3 deleted the channel-based `Party`/`Round`/`BaseUpdate` API +entirely, eliminating the attack surface those fixes protected. + +--- + +## Cross-Ceremony Replay Prevention + +**Problem:** v2 used hardcoded nonce=0 in all Fiat-Shamir challenges. +Two concurrent ceremonies with the same parties could replay proofs +across each other. + +**Fix:** Full SSID domain separation — every proof challenge includes +a protocol tag, curve params, party keys, party count, threshold, +round number, caller-supplied nonce, and ceremony ID. All encoded +with length-prefixed big.Int (not ambiguous raw concatenation). MtA +uses per-party directional session IDs. + +**Where:** `tss/params.go`, all `getSSID()`/`getSigningSSID()`/ +`getReshareSSID()` in `ecdsa/*/round_fn.go` and `eddsa/*/round_fn.go` + +--- + +## Message Redirection Prevention + +**Problem:** v2 P2P messages had no receiver binding. A malicious +relay could swap envelopes between parties, causing them to use each +other's shares silently. + +**Fix:** `ReceiverID` field on every P2P message. Receiver verifies +`msg.ReceiverID == myKey` before processing. + +**Where:** `ecdsa/*/messages.go`, `eddsa/keygen/messages.go`, +`eddsa/resharing/messages.go` — all P2P message types + +--- + +## Message Bounds Hardening + +**Problem:** v2 `ValidateBasic()` methods checked nil but not size. +An attacker could send 100MB coordinates and exhaust memory before +any crypto runs. + +**Fix:** Upper bounds on all fields: pubkey coords ≤ 33B, scalars ≤ +32B, commitments ≤ 32B, decommitments bounded per-element, Paillier +moduli ≤ 512B, proof arrays at exact expected sizes. + +**Where:** all `ValidateBasic()` in `ecdsa/*/messages.go` and +`eddsa/*/messages.go` + +--- + +## Identity Point / Zero Share Rejection + +**Problem:** v2 did not check for degenerate values. A zero Xi means +the party's contribution is annihilated during signing. An identity- +point public key makes verification equations trivially satisfiable. + +**Fix:** Every round that computes or receives key material checks: +Xi != 0, ECDSAPub/EDDSAPub != identity, BigXj != identity, nonce R +!= identity, accumulated S != 0. + +**Where:** `ecdsa/keygen/round_fn.go` (Round3/Round4), +`ecdsa/signing/round_fn.go` (SignRound5/7/9/Finalize), +`ecdsa/resharing/round_fn.go` (ReshareRound4/5), +`eddsa/keygen/round_fn.go` (Round3), `eddsa/signing/round_fn.go` +(SignRound3/Finalize), `eddsa/resharing/round_fn.go` (ReshareRound4) + +--- + +## Secret Zeroing + +**Problem:** v2 left secret key material in memory after use. A +memory disclosure bug would leak signing nonces (enabling share +recovery) or old Xi after resharing (enabling threshold reduction). + +**Fix:** Explicit zero after last use: ui after VSS, k/gamma/w/sigma +after signing, ri/wi after EdDSA signing, old Xi after resharing +(including dual-committee parties — v2 missed those). + +**Where:** `ecdsa/keygen/round_fn.go` (Round1), `ecdsa/signing/ +round_fn.go` (SignRound5), `ecdsa/resharing/round_fn.go` +(ReshareRound5), `eddsa/keygen/round_fn.go` (Round2), +`eddsa/signing/round_fn.go` (SignRound3), `eddsa/resharing/round_fn.go` +(ReshareRound5) + +--- + +## Modulus Validation Battery + +**Problem:** v2 accepted any Paillier N and NTilde without structural +checks. An attacker could submit a weak modulus (prime, small, even, +perfect square) and break the security assumptions of the proofs. + +**Fix:** Comprehensive battery in keygen Round 2: reject ≤2048-bit, +even, prime, perfect-square moduli. Reject duplicate/equal H1/H2/ +NTilde/PaillierN. Reject non-coprime H1/H2 with NTilde. + +**Where:** `ecdsa/keygen/round_fn.go` (Round2) + +--- + +## ZK Proof Hardening + +**Problem:** Multiple issues across MtA, Schnorr, DLN, Fac, Mod +proofs — missing range checks, missing nil validation, degenerate +Pedersen parameters, ciphertext coprimality bypass, sign-magnitude +encoding bug (~50% honest failure rate for FacProof). + +**Fix:** Per-proof fixes: +- MtA: s2/t2 upper bounds, Pedersen rejection, coprimality check, + nil validation, Paillier N minimum bitlen +- Schnorr: reject scalars outside [0,q), handle Add() error +- DLN: SSID session parameter, reject undersized moduli +- ModProof: reject undersized N, fail-fast on no quadratic residue +- FacProof: sign-magnitude V encoding (fixes ~50% honest failure) + +**Where:** `crypto/mta/*`, `crypto/schnorr/*`, `crypto/dlnproof/*`, +`crypto/facproof/*`, `crypto/modproof/*` + +--- + +## VSS Hardening + +**Problem:** v2 accepted zero/out-of-range shares and nil share IDs. +Duplicate share IDs (reduced mod q) could cause silent collisions. + +**Fix:** Reject zero/out-of-range shares, nil/zero share IDs. Detect +duplicate IDs. Nil-check ModInverse during Lagrange interpolation. +wi == 0 post-check after interpolation. + +**Where:** `crypto/vss/feldman_vss.go`, `ecdsa/signing/prepare.go`, +`eddsa/signing/prepare.go` + +--- + +## Signing Protocol Hardening + +**Problem:** Multiple edge cases in ECDSA signing: negative message, +zero theta, zero r (R.x mod N = 0), out-of-range partial sigs, +non-canonical S values. + +**Fix:** m >= 0 check, theta zero-check, r zero-check, per-party s_j +range check [0,N), S != 0, low-S normalization, ceiling division for +byte-length. + +**Where:** `ecdsa/signing/round_fn.go` + +--- + +## EdDSA-Specific Fixes + +**Problem:** EdDSA signing nonce R as identity leaks the full private +key (s = H(R,A,M)*a with no blinding). EdDSA cofactor-8 curve +allows small-order torsion points in commitments. + +**Fix:** R identity check in SignRound3. Cofactor clearing via +`EightInvEight()` on all unflattened VSS polynomial points in keygen +and resharing. Edwards curve singleton (fix for pointer identity +comparison in `ECPoint.Add()`). + +**Where:** `eddsa/signing/round_fn.go` (SignRound3), +`eddsa/keygen/round_fn.go` (Round3), `eddsa/resharing/round_fn.go` +(ReshareRound4), `tss/curve.go` (Edwards singleton) + +--- + +## Eliminated by v3 Architecture + +These v2 fixes are no longer needed because v3 removes the channel- +based state machine entirely: + +- **Key-at-Index verification** — v3 caller validates sender identity + before delivering to round functions +- **Duplicate message rejection** — v3 caller's indexed slot array + makes duplicates idempotent +- **local_party.go nil guards** — no local_party in v3 +- **Channel close races** — no channels in v3 protocol layer + +--- + +## Deferred Items + +Low-impact items carried from the v2 audit that don't affect +correctness or security in practice: + +1. MtA inverted lower-bound checks — don't reject honest proofs +2. ProofIters=13 — matches GG18 spec +3. BuildLocalSaveDataSubset panic — changing signature breaks callers +4. NSquare() caching — performance optimization only +5. MustGetRandomInt off-by-one — negligible for 256-bit +6. Concurrent io.Reader — safe with crypto/rand.Reader +7. CKD only for secp256k1 — by design +8. Commitment no domain separation — 256-bit nonce prevents collisions +9. Threshold=0 accepted — VSS rejects downstream +10. SHA512_256i sign-blindness — all callers pass non-negative diff --git a/tss-lib/cmd/tss-ecdsa-demo/main.go b/tss-lib/cmd/tss-ecdsa-demo/main.go new file mode 100644 index 0000000..a342bf6 --- /dev/null +++ b/tss-lib/cmd/tss-ecdsa-demo/main.go @@ -0,0 +1,507 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Command tss-ecdsa-demo is a reference implementation of the tss-lib +// v3 ECDSA round function API. It runs the full lifecycle in a single +// process: keygen → sign → reshare (overlapping committees) → sign. +// +// Note: Paillier safe-prime generation takes 10-60 seconds per party. +// +// Usage: +// +// go run ./cmd/tss-ecdsa-demo + +package main + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "fmt" + "math/big" + "os" + "time" + + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/resharing" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func main() { + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "FAIL: %v\n", err) + os.Exit(1) + } +} + +func run() error { + const minSigners = 2 // 2-of-3 + // tss-lib threshold parameter is t where t+1 parties sign. + const threshold = minSigners - 1 + ctx := context.Background() + + // ---------------------------------------------------------------- + // Party setup. 4 parties total — 3 old, 1 new joiner. + // + // Old committee: [P0, P1, P2] + // New committee: [P1, P2, P3] (P1, P2 overlap) + // ---------------------------------------------------------------- + allPIDs := tss.GenerateTestPartyIDs(4) + copyPID := func(src *tss.PartyID) *tss.PartyID { + return tss.NewPartyID(src.Id, src.Moniker, + new(big.Int).SetBytes(src.Key)) + } + oldPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[0]), copyPID(allPIDs[1]), copyPID(allPIDs[2]), + }) + newPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[1]), copyPID(allPIDs[2]), copyPID(allPIDs[3]), + }) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + oldN := len(oldPIDs) + newN := len(newPIDs) + + // ================================================================ + // PRE-PARAMETERS — Paillier safe primes (slow, do out-of-band) + // ================================================================ + fmt.Println("=== Generating Paillier pre-parameters (4 parties) ===") + allPreParams := make([]keygen.LocalPreParams, 4) + for i := range allPreParams { + start := time.Now() + pp, err := keygen.GeneratePreParams(5 * time.Minute) + if err != nil { + return fmt.Errorf("pre-params[%d]: %w", i, err) + } + allPreParams[i] = *pp + fmt.Printf(" party %d: %.1fs\n", i, time.Since(start).Seconds()) + } + oldPP := allPreParams[:3] + newPP := []keygen.LocalPreParams{allPreParams[1], allPreParams[2], allPreParams[3]} + + // ================================================================ + // KEYGEN — 4 rounds + // ================================================================ + fmt.Println("\n=== ECDSA Keygen (4 rounds) ===") + fmt.Printf(" parties: %d, threshold: %d-of-%d\n", + oldN, minSigners, oldN) + + saves, err := ecdsaKeygen(ctx, oldN, threshold, oldPIDs, oldCtx, oldPP) + if err != nil { + return fmt.Errorf("keygen: %w", err) + } + pubKey := saves[0].ECDSAPub + fmt.Printf(" public key: (%x...)\n", pubKey.X().Bytes()[:8]) + + // ================================================================ + // SIGN — 9 rounds + finalize + // ================================================================ + fmt.Println("\n=== ECDSA Sign (9 rounds + finalize) ===") + msg1 := sha256.Sum256([]byte("pre-reshare message")) + sig1, err := ecdsaSign(ctx, oldN, threshold, oldPIDs, oldCtx, saves, + new(big.Int).SetBytes(msg1[:])) + if err != nil { + return fmt.Errorf("sign: %w", err) + } + if err := verifyECDSA(pubKey, msg1[:], sig1); err != nil { + return fmt.Errorf("verify: %w", err) + } + fmt.Printf(" message: %x\n", msg1[:8]) + fmt.Printf(" signature: R=%x S=%x\n", sig1.R[:8], sig1.S[:8]) + fmt.Println(" verified: OK") + + // ================================================================ + // RESHARE — 5 rounds, overlapping committees + // ================================================================ + fmt.Println("\n=== ECDSA Reshare (5 rounds, overlapping) ===") + fmt.Printf(" old committee: [%s, %s, %s]\n", + oldPIDs[0].Id, oldPIDs[1].Id, oldPIDs[2].Id) + fmt.Printf(" new committee: [%s, %s, %s]\n", + newPIDs[0].Id, newPIDs[1].Id, newPIDs[2].Id) + + newSaves, err := ecdsaReshare(ctx, oldPIDs, newPIDs, oldCtx, newCtx, + saves, oldPP, newPP, threshold, threshold) + if err != nil { + return fmt.Errorf("reshare: %w", err) + } + if !newSaves[0].ECDSAPub.Equals(pubKey) { + return fmt.Errorf("public key changed after reshare") + } + fmt.Printf(" public key preserved: (%x...)\n", pubKey.X().Bytes()[:8]) + + // ================================================================ + // SIGN AGAIN — with new committee + // ================================================================ + fmt.Println("\n=== ECDSA Sign (new committee) ===") + msg2 := sha256.Sum256([]byte("post-reshare message")) + sig2, err := ecdsaSign(ctx, newN, threshold, newPIDs, newCtx, newSaves, + new(big.Int).SetBytes(msg2[:])) + if err != nil { + return fmt.Errorf("sign2: %w", err) + } + if err := verifyECDSA(pubKey, msg2[:], sig2); err != nil { + return fmt.Errorf("verify2: %w", err) + } + fmt.Printf(" message: %x\n", msg2[:8]) + fmt.Printf(" signature: R=%x S=%x\n", sig2.R[:8], sig2.S[:8]) + fmt.Println(" verified: OK") + + fmt.Println("\n=== SUCCESS ===") + return nil +} + +// ------------------------------------------------------------------- +// Keygen: 4 rounds +// +// Round 1: VSS polynomial + commitment, Paillier pub key +// Round 2: P2P shares + decommitment + Schnorr proof + DLN proofs +// Round 3: verify decommitments, Schnorr proofs, shares +// Round 4: verify Paillier/mod/fac proofs, save +// ------------------------------------------------------------------- + +func ecdsaKeygen(ctx context.Context, n, threshold int, pIDs tss.SortedPartyIDs, peerCtx *tss.PeerContext, preParams []keygen.LocalPreParams) ([]keygen.LocalPartySaveData, error) { + // -- Round 1 -- + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(ctx, params, preParams[i]) + if err != nil { + return nil, fmt.Errorf("round1[%d]: %w", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + // -- Round 2 -- + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(ctx, states[i], r1) + if err != nil { + return nil, fmt.Errorf("round2[%d]: %w", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + // -- Round 3 -- + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(ctx, states[i], r2p2p[i], r2bcast) + if err != nil { + return nil, fmt.Errorf("round3[%d]: %w", i, err) + } + r3[i] = out.Messages[0] + } + + // -- Round 4 -- + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(ctx, states[i], r3) + if err != nil { + return nil, fmt.Errorf("round4[%d]: %w", i, err) + } + saves[i] = *out.Save + } + return saves, nil +} + +// ------------------------------------------------------------------- +// Sign: 9 rounds + finalize +// +// Round 1: k, gamma, MtA ciphertext (P2P) + commitment (broadcast) +// Round 2: MtA response (P2P) +// Round 3: theta, sigma (broadcast) +// Round 4: Schnorr proof for gamma (broadcast) +// Round 5: verify commitments, compute R (broadcast) +// Round 6: Schnorr proof for blinding (broadcast) +// Round 7: verify blinding, commit Ui/Ti (broadcast) +// Round 8: decommit Ui/Ti (broadcast) +// Round 9: verify Ui==Ti, reveal si (broadcast) +// Finalize: sum partial sigs, verify ECDSA signature +// ------------------------------------------------------------------- + +func ecdsaSign(ctx context.Context, n, threshold int, pIDs tss.SortedPartyIDs, peerCtx *tss.PeerContext, saves []keygen.LocalPartySaveData, m *big.Int) (*signing.SignatureData, error) { + // -- Round 1: P2P + broadcast -- + states := make([]*signing.SigningState, n) + r1p2p := make([][]*tss.Message, n) + r1bcast := make([]*tss.Message, n) + for i := range r1p2p { + r1p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := signing.SignRound1(params, saves[i], m, nil, 0) + if err != nil { + return nil, fmt.Errorf("signR1[%d]: %w", i, err) + } + states[i] = st + for _, msg := range out.Messages { + if msg.To == nil { + r1bcast[i] = msg + } else { + for _, to := range msg.To { + r1p2p[to.Index][i] = msg + } + } + } + } + + // -- Round 2: P2P -- + r2p2p := make([][]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := signing.SignRound2(ctx, states[i], r1p2p[i], r1bcast) + if err != nil { + return nil, fmt.Errorf("signR2[%d]: %w", i, err) + } + for _, msg := range out.Messages { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + + // -- Round 3: broadcast -- + r3 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound3(ctx, states[i], r2p2p[i]) + }, "signR3") + if r3 == nil { + return nil, fmt.Errorf("signR3 failed") + } + + // -- Rounds 4-9: all broadcast -- + r4 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound4(states[i], r3) + }, "signR4") + r5 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound5(states[i], r4) + }, "signR5") + r6 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound6(states[i]) + }, "signR6") + r7 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound7(states[i], r5, r6) + }, "signR7") + r8 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound8(states[i]) + }, "signR8") + r9 := bcastRound(n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound9(states[i], r7, r8) + }, "signR9") + + // -- Finalize -- + out, err := signing.SignFinalize(states[0], r9) + if err != nil { + return nil, fmt.Errorf("signFinalize: %w", err) + } + return out.Signature, nil +} + +func bcastRound(n int, states []*signing.SigningState, fn func(int) (*signing.SignRoundOutput, error), name string) []*tss.Message { + msgs := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := fn(i) + if err != nil { + fmt.Fprintf(os.Stderr, "%s[%d]: %v\n", name, i, err) + return nil + } + msgs[i] = out.Messages[0] + } + return msgs +} + +// ------------------------------------------------------------------- +// Reshare: 5 rounds, overlapping committees +// +// Round 1: old → VSS commitment + ECDSA pub (broadcast to new) +// Round 2: new → Paillier/DLN params (broadcast to new) + ACK (to old) +// Round 3: old → P2P shares + decommitment (to new) +// Round 4: new → verify shares, FacProof P2P + ACK broadcast +// Round 5: save new key material, zero old Xi +// ------------------------------------------------------------------- + +func ecdsaReshare(ctx context.Context, oldPIDs, newPIDs tss.SortedPartyIDs, oldCtx, newCtx *tss.PeerContext, oldSaves []keygen.LocalPartySaveData, oldPP, newPP []keygen.LocalPreParams, oldT, newT int) ([]keygen.LocalPartySaveData, error) { + oldN := len(oldPIDs) + newN := len(newPIDs) + + type party struct { + pid *tss.PartyID + oldIdx int + newIdx int + state *resharing.ReshareState + } + seen := make(map[string]*party) + all := make([]*party, 0, oldN+1) // at most oldN + new-only parties + for i, pid := range oldPIDs { + key := fmt.Sprintf("%x", pid.Key) + p := &party{pid: pid, oldIdx: i, newIdx: -1} + seen[key] = p + all = append(all, p) + } + for i, pid := range newPIDs { + key := fmt.Sprintf("%x", pid.Key) + if p, ok := seen[key]; ok { + p.newIdx = i + } else { + p := &party{pid: pid, oldIdx: -1, newIdx: i} + seen[key] = p + all = append(all, p) + } + } + + // -- Round 1 -- + r1Msgs := make([]*tss.Message, oldN) + for _, p := range all { + params := tss.NewReSharingParameters( + tss.S256(), oldCtx, newCtx, p.pid, + oldN, oldT, newN, newT) + params.SetNoProofMod() + params.SetNoProofFac() + params.SetNoProofDLN() + var key keygen.LocalPartySaveData + var pp keygen.LocalPreParams + if p.oldIdx >= 0 { + key = oldSaves[p.oldIdx] + } else { + key = keygen.NewLocalPartySaveData(oldN) + } + if p.newIdx >= 0 { + pp = newPP[p.newIdx] + } + st, out, err := resharing.ReshareRound1(params, key, pp) + if err != nil { + return nil, fmt.Errorf("reshareR1[%s]: %w", p.pid.Id, err) + } + p.state = st + if p.oldIdx >= 0 && len(out.Messages) > 0 { + r1Msgs[p.oldIdx] = out.Messages[0] + } + } + + // -- Round 2 -- + r2Msg1s := make([]*tss.Message, newN) // DGRound2Message1 (to new) + r2Msg2s := make([]*tss.Message, newN) // DGRound2Message2 (ACK to old) + for _, p := range all { + out, err := resharing.ReshareRound2(p.state, r1Msgs) + if err != nil { + return nil, fmt.Errorf("reshareR2[%s]: %w", p.pid.Id, err) + } + if p.newIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound2Message1: + r2Msg1s[p.newIdx] = msg + case *resharing.DGRound2Message2: + r2Msg2s[p.newIdx] = msg + } + } + } + } + + // -- Round 3 -- + r3P2P := make([][]*tss.Message, newN) + r3Bcast := make([]*tss.Message, oldN) + for i := range r3P2P { + r3P2P[i] = make([]*tss.Message, oldN) + } + for _, p := range all { + out, err := resharing.ReshareRound3(p.state, r2Msg2s) + if err != nil { + return nil, fmt.Errorf("reshareR3[%s]: %w", p.pid.Id, err) + } + if p.oldIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound3Message2: + r3Bcast[p.oldIdx] = msg + case *resharing.DGRound3Message1: + for _, to := range msg.To { + r3P2P[to.Index][p.oldIdx] = msg + } + } + } + } + } + + // -- Round 4 -- + r4P2P := make([][]*tss.Message, newN) + r4Bcast := make([]*tss.Message, newN) + for i := range r4P2P { + r4P2P[i] = make([]*tss.Message, newN) + } + for _, p := range all { + var myR3P2P []*tss.Message + if p.newIdx >= 0 { + myR3P2P = r3P2P[p.newIdx] + } + out, err := resharing.ReshareRound4(ctx, p.state, r2Msg1s, myR3P2P, r3Bcast) + if err != nil { + return nil, fmt.Errorf("reshareR4[%s]: %w", p.pid.Id, err) + } + if p.newIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound4Message1: + for _, to := range msg.To { + r4P2P[to.Index][p.newIdx] = msg + } + case *resharing.DGRound4Message2: + r4Bcast[p.newIdx] = msg + } + } + } + } + + // -- Round 5 -- + newSaves := make([]keygen.LocalPartySaveData, newN) + for _, p := range all { + var myR4P2P []*tss.Message + if p.newIdx >= 0 { + myR4P2P = r4P2P[p.newIdx] + } + out, err := resharing.ReshareRound5(p.state, myR4P2P, r4Bcast) + if err != nil { + return nil, fmt.Errorf("reshareR5[%s]: %w", p.pid.Id, err) + } + if p.newIdx >= 0 { + newSaves[p.newIdx] = *out.Save + } + } + return newSaves, nil +} + +// ecPoint is a point on an elliptic curve with X and Y coordinates. +type ecPoint interface { + X() *big.Int + Y() *big.Int +} + +func verifyECDSA(pub ecPoint, msg []byte, sig *signing.SignatureData) error { + pk := &ecdsa.PublicKey{Curve: tss.S256(), X: pub.X(), Y: pub.Y()} + r := new(big.Int).SetBytes(sig.R) + s := new(big.Int).SetBytes(sig.S) + if !ecdsa.Verify(pk, msg, r, s) { + return fmt.Errorf("ECDSA signature verification failed") + } + return nil +} diff --git a/tss-lib/cmd/tss-eddsa-demo/main.go b/tss-lib/cmd/tss-eddsa-demo/main.go new file mode 100644 index 0000000..7c15596 --- /dev/null +++ b/tss-lib/cmd/tss-eddsa-demo/main.go @@ -0,0 +1,402 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Command tss-eddsa-demo is a reference implementation of the tss-lib +// v3 EdDSA round function API. It runs the full lifecycle in a single +// process: keygen → sign → reshare (overlapping committees) → sign. +// +// Usage: +// +// go run ./cmd/tss-eddsa-demo + +package main + +import ( + "crypto/sha256" + "fmt" + "math/big" + "os" + + "github.com/decred/dcrd/dcrec/edwards/v2" + + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/eddsa/resharing" + "github.com/hemilabs/x/tss-lib/v3/eddsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func main() { + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "FAIL: %v\n", err) + os.Exit(1) + } +} + +func run() error { + const minSigners = 2 // 2-of-3 + // tss-lib threshold parameter is t where t+1 parties sign. + const threshold = minSigners - 1 + + // ---------------------------------------------------------------- + // Party setup. 4 parties total — 3 old, 1 new joiner. + // + // Old committee: [P0, P1, P2] + // New committee: [P1, P2, P3] (P1, P2 overlap) + // + // Each committee needs its own *PartyID copies because + // SortPartyIDs assigns .Index by sort position — sharing + // objects between committees corrupts the indices. + // ---------------------------------------------------------------- + allPIDs := tss.GenerateTestPartyIDs(4) + copyPID := func(src *tss.PartyID) *tss.PartyID { + return tss.NewPartyID(src.Id, src.Moniker, + new(big.Int).SetBytes(src.Key)) + } + oldPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[0]), copyPID(allPIDs[1]), copyPID(allPIDs[2]), + }) + newPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[1]), copyPID(allPIDs[2]), copyPID(allPIDs[3]), + }) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + oldN := len(oldPIDs) + newN := len(newPIDs) + + // ================================================================ + // KEYGEN — 3 rounds, no Paillier + // ================================================================ + fmt.Println("=== EdDSA Keygen (3 rounds) ===") + fmt.Printf(" parties: %d, threshold: %d-of-%d\n", + oldN, minSigners, oldN) + + saves, err := eddsaKeygen(oldN, threshold, oldPIDs, oldCtx) + if err != nil { + return fmt.Errorf("keygen: %w", err) + } + pubKey := saves[0].EDDSAPub + fmt.Printf(" public key: (%x, %x)\n", pubKey.X(), pubKey.Y()) + + // ================================================================ + // SIGN — 3 rounds + finalize + // ================================================================ + fmt.Println("\n=== EdDSA Sign (3 rounds + finalize) ===") + msg1 := sha256.Sum256([]byte("pre-reshare message")) + sig1, err := eddsaSign(oldN, threshold, oldPIDs, oldCtx, saves, + new(big.Int).SetBytes(msg1[:])) + if err != nil { + return fmt.Errorf("sign: %w", err) + } + if err := verifyEdDSA(pubKey, msg1[:], sig1); err != nil { + return fmt.Errorf("verify: %w", err) + } + fmt.Printf(" message: %x\n", msg1[:8]) + fmt.Printf(" signature: R=%x S=%x\n", sig1.R[:8], sig1.S[:8]) + fmt.Println(" verified: OK") + + // ================================================================ + // RESHARE — 5 rounds, overlapping committees + // ================================================================ + fmt.Println("\n=== EdDSA Reshare (5 rounds, overlapping) ===") + fmt.Printf(" old committee: [%s, %s, %s]\n", + oldPIDs[0].Id, oldPIDs[1].Id, oldPIDs[2].Id) + fmt.Printf(" new committee: [%s, %s, %s]\n", + newPIDs[0].Id, newPIDs[1].Id, newPIDs[2].Id) + + newSaves, err := eddsaReshare(oldPIDs, newPIDs, oldCtx, newCtx, + saves, threshold, threshold) + if err != nil { + return fmt.Errorf("reshare: %w", err) + } + newPubKey := newSaves[0].EDDSAPub + if !newPubKey.Equals(pubKey) { + return fmt.Errorf("public key changed after reshare") + } + if saves[0].Xi.Sign() != 0 { + return fmt.Errorf("P0 Xi not zeroed after reshare") + } + fmt.Printf(" public key preserved: (%x, %x)\n", + newPubKey.X(), newPubKey.Y()) + fmt.Println(" old P0 Xi zeroed: OK") + + // ================================================================ + // SIGN AGAIN — with new committee + // ================================================================ + fmt.Println("\n=== EdDSA Sign (new committee) ===") + msg2 := sha256.Sum256([]byte("post-reshare message")) + sig2, err := eddsaSign(newN, threshold, newPIDs, newCtx, newSaves, + new(big.Int).SetBytes(msg2[:])) + if err != nil { + return fmt.Errorf("sign2: %w", err) + } + if err := verifyEdDSA(pubKey, msg2[:], sig2); err != nil { + return fmt.Errorf("verify2: %w", err) + } + fmt.Printf(" message: %x\n", msg2[:8]) + fmt.Printf(" signature: R=%x S=%x\n", sig2.R[:8], sig2.S[:8]) + fmt.Println(" verified: OK") + + fmt.Println("\n=== SUCCESS ===") + return nil +} + +// ------------------------------------------------------------------- +// Keygen: 3 rounds +// +// Round 1: each party generates VSS polynomial, broadcasts commitment +// Round 2: each party sends P2P shares, broadcasts decommitment + Schnorr proof +// Round 3: each party verifies proofs and shares, computes public key +// ------------------------------------------------------------------- + +func eddsaKeygen(n, threshold int, pIDs tss.SortedPartyIDs, ctx *tss.PeerContext) ([]keygen.LocalPartySaveData, error) { + // -- Round 1 -- + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), ctx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(params) + if err != nil { + return nil, fmt.Errorf("round1[%d]: %w", i, err) + } + states[i] = st + r1[i] = out.Messages[0] // broadcast: commitment + } + + // -- Round 2 -- + // Produces two kinds of messages: + // P2P (msg.To != nil): VSS share for one specific party + // Broadcast (msg.To == nil): decommitment + Schnorr proof + r2p2p := make([][]*tss.Message, n) // r2p2p[receiver][sender] + r2bcast := make([]*tss.Message, n) // r2bcast[sender] + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(states[i], r1) + if err != nil { + return nil, fmt.Errorf("round2[%d]: %w", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + // Own P2P share and broadcast are stored in state for self. + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + // -- Round 3 -- + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + return nil, fmt.Errorf("round3[%d]: %w", i, err) + } + saves[i] = *out.Save + } + return saves, nil +} + +// ------------------------------------------------------------------- +// Sign: 3 rounds + finalize +// +// Round 1: each party picks nonce ri, broadcasts commitment to Ri +// Round 2: each party broadcasts decommitment + Schnorr proof for ri +// Round 3: each party verifies proofs, computes aggregate R, +// produces partial signature si +// Finalize: sum partial sigs, verify EdDSA signature +// ------------------------------------------------------------------- + +func eddsaSign(n, threshold int, pIDs tss.SortedPartyIDs, ctx *tss.PeerContext, saves []keygen.LocalPartySaveData, m *big.Int) (*signing.SignatureData, error) { + // -- Round 1 -- + states := make([]*signing.SigningState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), ctx, pIDs[i], n, threshold) + st, out, err := signing.SignRound1(params, saves[i], m, 0) + if err != nil { + return nil, fmt.Errorf("signRound1[%d]: %w", i, err) + } + states[i] = st + r1[i] = out.Messages[0] // broadcast: commitment + } + + // -- Round 2 -- + r2 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound2(states[i], r1) + if err != nil { + return nil, fmt.Errorf("signRound2[%d]: %w", i, err) + } + r2[i] = out.Messages[0] // broadcast: decommit + proof + } + + // -- Round 3 -- + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound3(states[i], r2) + if err != nil { + return nil, fmt.Errorf("signRound3[%d]: %w", i, err) + } + r3[i] = out.Messages[0] // broadcast: partial sig si + } + + // -- Finalize -- + out, err := signing.SignFinalize(states[0], r3) + if err != nil { + return nil, fmt.Errorf("signFinalize: %w", err) + } + return out.Signature, nil +} + +// ------------------------------------------------------------------- +// Reshare: 5 rounds, supports overlapping committees +// +// Round 1: old committee computes Lagrange wi, creates VSS for new, +// broadcasts commitment + EdDSA pub to new committee +// Round 2: new committee validates pub key consistency, ACKs old +// Round 3: old committee sends P2P shares + decommitment to new +// Round 4: new committee verifies shares and commitments, ACKs both +// Round 5: new committee saves new key material, old zeros Xi +// ------------------------------------------------------------------- + +func eddsaReshare(oldPIDs, newPIDs tss.SortedPartyIDs, oldCtx, newCtx *tss.PeerContext, oldSaves []keygen.LocalPartySaveData, oldT, newT int) ([]keygen.LocalPartySaveData, error) { + oldN := len(oldPIDs) + newN := len(newPIDs) + + // Build participant roster. A party can be in old, new, or both. + type party struct { + pid *tss.PartyID + oldIdx int // -1 if new-only + newIdx int // -1 if old-only + state *resharing.ReshareState + } + seen := make(map[string]*party) + all := make([]*party, 0, oldN+1) + for i, pid := range oldPIDs { + key := fmt.Sprintf("%x", pid.Key) + p := &party{pid: pid, oldIdx: i, newIdx: -1} + seen[key] = p + all = append(all, p) + } + for i, pid := range newPIDs { + key := fmt.Sprintf("%x", pid.Key) + if p, ok := seen[key]; ok { + p.newIdx = i // dual-committee + } else { + p := &party{pid: pid, oldIdx: -1, newIdx: i} + seen[key] = p + all = append(all, p) + } + } + + // -- Round 1: old committee produces, new no-ops -- + r1Msgs := make([]*tss.Message, oldN) + for _, p := range all { + params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, p.pid, + oldN, oldT, newN, newT) + var input *keygen.LocalPartySaveData + if p.oldIdx >= 0 { + input = &oldSaves[p.oldIdx] + } + st, out, err := resharing.ReshareRound1(params, input) + if err != nil { + return nil, fmt.Errorf("reshareR1[%s]: %w", p.pid.Id, err) + } + p.state = st + if p.oldIdx >= 0 && len(out.Messages) > 0 { + r1Msgs[p.oldIdx] = out.Messages[0] + } + } + + // -- Round 2: new committee ACKs -- + r2Msgs := make([]*tss.Message, newN) + for _, p := range all { + out, err := resharing.ReshareRound2(p.state, r1Msgs) + if err != nil { + return nil, fmt.Errorf("reshareR2[%s]: %w", p.pid.Id, err) + } + if p.newIdx >= 0 && len(out.Messages) > 0 { + r2Msgs[p.newIdx] = out.Messages[0] + } + } + + // -- Round 3: old sends shares + decommitment -- + r3p2p := make([][]*tss.Message, newN) // r3p2p[newReceiver][oldSender] + r3bcast := make([]*tss.Message, oldN) + for i := range r3p2p { + r3p2p[i] = make([]*tss.Message, oldN) + } + for _, p := range all { + out, err := resharing.ReshareRound3(p.state, r2Msgs) + if err != nil { + return nil, fmt.Errorf("reshareR3[%s]: %w", p.pid.Id, err) + } + if p.oldIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound3Message2: + r3bcast[p.oldIdx] = msg + case *resharing.DGRound3Message1: + for _, to := range msg.To { + r3p2p[to.Index][p.oldIdx] = msg + } + } + } + } + } + + // -- Round 4: new committee verifies -- + r4Msgs := make([]*tss.Message, newN) + for _, p := range all { + var myP2P []*tss.Message + if p.newIdx >= 0 { + myP2P = r3p2p[p.newIdx] + } + out, err := resharing.ReshareRound4(p.state, r1Msgs, myP2P, r3bcast) + if err != nil { + return nil, fmt.Errorf("reshareR4[%s]: %w", p.pid.Id, err) + } + if p.newIdx >= 0 && len(out.Messages) > 0 { + r4Msgs[p.newIdx] = out.Messages[0] + } + } + + // -- Round 5: save -- + newSaves := make([]keygen.LocalPartySaveData, newN) + for _, p := range all { + out, err := resharing.ReshareRound5(p.state, r4Msgs) + if err != nil { + return nil, fmt.Errorf("reshareR5[%s]: %w", p.pid.Id, err) + } + if p.newIdx >= 0 { + newSaves[p.newIdx] = *out.Save + } + } + return newSaves, nil +} + +// ecPoint is a point on an elliptic curve with X and Y coordinates. +type ecPoint interface { + X() *big.Int + Y() *big.Int +} + +func verifyEdDSA(pub ecPoint, msg []byte, sig *signing.SignatureData) error { + pk := edwards.PublicKey{Curve: tss.Edwards(), X: pub.X(), Y: pub.Y()} + r := new(big.Int).SetBytes(sig.R) + s := new(big.Int).SetBytes(sig.S) + if !edwards.Verify(&pk, msg, r, s) { + return fmt.Errorf("EdDSA signature verification failed") + } + return nil +} diff --git a/tss-lib/common/common_fork_test.go b/tss-lib/common/common_fork_test.go new file mode 100644 index 0000000..0a41650 --- /dev/null +++ b/tss-lib/common/common_fork_test.go @@ -0,0 +1,233 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Tests for fork changes in common utility functions. + +package common + +import ( + "crypto/rand" + "math/big" + "reflect" + "testing" +) + +// --- SHA512_256i nil guard (hash.go:73) --- + +func TestSHA512_256iNilInput(t *testing.T) { + // [FORK] nil big.Int in input should be treated as zero, not panic + result := SHA512_256i(big.NewInt(1), nil, big.NewInt(3)) + if result == nil { + t.Fatal("SHA512_256i should handle nil input without panic") + } + + // Result should match hashing with explicit zero + expected := SHA512_256i(big.NewInt(1), big.NewInt(0), big.NewInt(3)) + if result.Cmp(expected) != 0 { + t.Fatalf("nil should hash as zero") + } +} + +// --- SHA512_256i_TAGGED nil guard --- + +func TestSHA512_256iTaggedNilInput(t *testing.T) { + tag := []byte("test-tag") + result := SHA512_256i_TAGGED(tag, big.NewInt(1), nil, big.NewInt(3)) + if result == nil { + t.Fatal("SHA512_256i_TAGGED should handle nil input without panic") + } + + expected := SHA512_256i_TAGGED(tag, big.NewInt(1), big.NewInt(0), big.NewInt(3)) + if result.Cmp(expected) != 0 { + t.Fatalf("nil should hash as zero in tagged variant") + } +} + +// --- RejectionSample no in-place mutation (hash_utils.go:24) --- + +func TestRejectionSampleNoMutation(t *testing.T) { + // [FORK] Upstream mutates eHash in-place. Fork allocates new big.Int. + q := big.NewInt(97) // small prime for testing + eHash := big.NewInt(150) + eHashCopy := new(big.Int).Set(eHash) + + result := RejectionSample(q, eHash) + + // eHash should NOT be modified + if eHash.Cmp(eHashCopy) != 0 { + t.Fatalf("RejectionSample must not mutate eHash") + } + // Result should be eHash mod q + expected := new(big.Int).Mod(eHashCopy, q) + if result.Cmp(expected) != 0 { + t.Fatalf("result should be eHash mod q") + } +} + +// --- IsInInterval nil guard (int.go:60) --- + +func TestIsInIntervalNilB(t *testing.T) { + if IsInInterval(nil, big.NewInt(10)) { + t.Fatal("nil b should return false") + } +} + +func TestIsInIntervalNilBound(t *testing.T) { + if IsInInterval(big.NewInt(5), nil) { + t.Fatal("nil bound should return false") + } +} + +func TestIsInIntervalBothNil(t *testing.T) { + if IsInInterval(nil, nil) { + t.Fatal("both nil should return false") + } +} + +func TestIsInIntervalValid(t *testing.T) { + if !(IsInInterval(big.NewInt(5), big.NewInt(10))) { + t.Fatal("5 in [0, 10) should be true") + } + if IsInInterval(big.NewInt(10), big.NewInt(10)) { + t.Fatal("10 not in [0, 10)") + } + if IsInInterval(big.NewInt(-1), big.NewInt(10)) { + t.Fatal("-1 not in [0, 10)") + } +} + +// --- AppendBigIntToBytesSlice length-prefixed (int.go:75) --- + +func TestAppendBigIntToBytesSlice(t *testing.T) { + // [FORK] Uses length prefix to distinguish zero from absent + base := []byte{0xAA, 0xBB} + + // Append zero: should get [AA BB 00 00 00 00] (4-byte length prefix, no data) + result := AppendBigIntToBytesSlice(base, big.NewInt(0)) + if len(result) != 6 { + t.Fatalf("zero value should append 4-byte length prefix only") + } + if byte(0xAA) != result[0] { + t.Fatalf("got %v, want %v", result[0], byte(0xAA)) + } + if byte(0xBB) != result[1] { + t.Fatalf("got %v, want %v", result[1], byte(0xBB)) + } + // Length should be 0 (big-endian) + if byte(0) != result[2] { + t.Fatalf("got %v, want %v", result[2], byte(0)) + } + if byte(0) != result[3] { + t.Fatalf("got %v, want %v", result[3], byte(0)) + } + if byte(0) != result[4] { + t.Fatalf("got %v, want %v", result[4], byte(0)) + } + if byte(0) != result[5] { + t.Fatalf("got %v, want %v", result[5], byte(0)) + } + + // Append non-zero + result2 := AppendBigIntToBytesSlice(base, big.NewInt(256)) + // 256 = 0x0100, so 2 bytes + if len(result2) != 8 { + t.Fatalf("256 should append 4-byte length + 2 data bytes") + } + if byte(0) != result2[2] { + t.Fatalf("got %v, want %v", result2[2], byte(0)) + } + if byte(0) != result2[3] { + t.Fatalf("got %v, want %v", result2[3], byte(0)) + } + if byte(0) != result2[4] { + t.Fatalf("got %v, want %v", result2[4], byte(0)) + } + if byte(2) != result2[5] { + t.Fatalf("got %v, want %v", result2[5], byte(2)) + } + + // Append nil: should be same as zero + resultNil := AppendBigIntToBytesSlice(base, nil) + if len(resultNil) != 6 { + t.Fatalf("nil should append 4-byte length prefix (zero length)") + } +} + +func TestAppendBigIntToBytesSliceDoesNotMutateBase(t *testing.T) { + base := []byte{0xAA, 0xBB} + baseCopy := make([]byte, len(base)) + copy(baseCopy, base) + + _ = AppendBigIntToBytesSlice(base, big.NewInt(42)) + + if !reflect.DeepEqual(baseCopy, base) { + t.Fatalf("base slice should not be mutated") + } +} + +// --- GetRandomPositiveInt rejects lessThan < 2 (random.go:45) --- + +func TestGetRandomPositiveIntRejectsNil(t *testing.T) { + result := GetRandomPositiveInt(rand.Reader, nil) + if result != nil { + t.Fatalf("expected nil, got %v", result) + } +} + +func TestGetRandomPositiveIntRejectsZero(t *testing.T) { + result := GetRandomPositiveInt(rand.Reader, big.NewInt(0)) + if result != nil { + t.Fatalf("expected nil, got %v", result) + } +} + +func TestGetRandomPositiveIntRejectsOne(t *testing.T) { + // [FORK] lessThan=1 means interval [1, 1) is empty. Upstream allowed this. + result := GetRandomPositiveInt(rand.Reader, big.NewInt(1)) + if result != nil { + t.Fatalf("expected nil, got %v", result) + } +} + +func TestGetRandomPositiveIntAcceptsTwo(t *testing.T) { + // lessThan=2 -> only valid result is 1 + result := GetRandomPositiveInt(rand.Reader, big.NewInt(2)) + if result == nil { + t.Fatal("expected non-nil") + } + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("only valid positive int less than 2 is 1") + } +} + +// --- PadToLengthBytesInPlace (slice.go:59) --- + +func TestPadToLengthBytesInPlace(t *testing.T) { + // Shorter than target: should be zero-padded on the left + src := []byte{0x01, 0x02} + result := PadToLengthBytesInPlace(src, 4) + if !reflect.DeepEqual([]byte{0x00, 0x00, 0x01, 0x02}, result) { + t.Fatalf("got %v, want %v", result, []byte{0x00, 0x00, 0x01, 0x02}) + } + + // Already correct length: should return as-is + src2 := []byte{0x01, 0x02, 0x03, 0x04} + result2 := PadToLengthBytesInPlace(src2, 4) + if !reflect.DeepEqual(src2, result2) { + t.Fatalf("got %v, want %v", result2, src2) + } + + // Longer than target: should return as-is (no truncation) + src3 := []byte{0x01, 0x02, 0x03, 0x04, 0x05} + result3 := PadToLengthBytesInPlace(src3, 4) + if !reflect.DeepEqual(src3, result3) { + t.Fatalf("got %v, want %v", result3, src3) + } + + // Empty source + result4 := PadToLengthBytesInPlace([]byte{}, 3) + if !reflect.DeepEqual([]byte{0x00, 0x00, 0x00}, result4) { + t.Fatalf("got %v, want %v", result4, []byte{0x00, 0x00, 0x00}) + } +} diff --git a/tss-lib/common/coverage_test.go b/tss-lib/common/coverage_test.go new file mode 100644 index 0000000..afd72e8 --- /dev/null +++ b/tss-lib/common/coverage_test.go @@ -0,0 +1,200 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package common + +import ( + "crypto/rand" + "math/big" + "testing" +) + +// --- slice.go --- + +func TestNonEmptyBytes(t *testing.T) { + if NonEmptyBytes(nil) { + t.Fatal("nil should fail") + } + if NonEmptyBytes([]byte{}) { + t.Fatal("empty should fail") + } + if !NonEmptyBytes([]byte{0x01}) { + t.Fatal("non-empty should pass") + } +} + +func TestNonEmptyMultiBytes(t *testing.T) { + if NonEmptyMultiBytes(nil) { + t.Fatal("nil should fail") + } + if NonEmptyMultiBytes([][]byte{}) { + t.Fatal("empty slice should fail") + } + if NonEmptyMultiBytes([][]byte{{0x01}, nil}) { + t.Fatal("contains nil should fail") + } + if NonEmptyMultiBytes([][]byte{{0x01}, {}}) { + t.Fatal("contains empty should fail") + } + if NonEmptyMultiBytes([][]byte{{0x01}}, 2) { + t.Fatal("wrong expectLen should fail") + } + if !NonEmptyMultiBytes([][]byte{{0x01}, {0x02}}) { + t.Fatal("valid should pass") + } + if !NonEmptyMultiBytes([][]byte{{0x01}, {0x02}}, 2) { + t.Fatal("valid with expectLen should pass") + } +} + +func TestBigIntsToBytesAndBack(t *testing.T) { + input := []*big.Int{big.NewInt(42), nil, big.NewInt(99)} + bzs := BigIntsToBytes(input) + if len(bzs) != 3 { + t.Fatalf("want 3, got %d", len(bzs)) + } + if bzs[1] != nil { + t.Fatal("nil big.Int should produce nil bytes") + } + + back := MultiBytesToBigInts(bzs[:1]) + if back[0].Cmp(big.NewInt(42)) != 0 { + t.Fatalf("round-trip failed: got %v", back[0]) + } +} + +func TestPadToLengthBytesInPlaceEdgeCases(t *testing.T) { + src := []byte{0x01, 0x02} + padded := PadToLengthBytesInPlace(src, 4) + if len(padded) != 4 { + t.Fatalf("want 4, got %d", len(padded)) + } + if padded[0] != 0 || padded[1] != 0 || padded[2] != 1 || padded[3] != 2 { + t.Fatalf("padding wrong: %x", padded) + } + + // Already long enough + long := []byte{0x01, 0x02, 0x03, 0x04, 0x05} + same := PadToLengthBytesInPlace(long, 3) + if len(same) != 5 { + t.Fatal("should not truncate") + } +} + +// --- random.go --- + +func TestGetRandomBytes(t *testing.T) { + bz, err := GetRandomBytes(rand.Reader, 32) + if err != nil { + t.Fatal(err) + } + if len(bz) != 32 { + t.Fatalf("want 32, got %d", len(bz)) + } + + _, err = GetRandomBytes(rand.Reader, 0) + if err == nil { + t.Fatal("length 0 should fail") + } + _, err = GetRandomBytes(rand.Reader, -1) + if err == nil { + t.Fatal("negative length should fail") + } +} + +func TestGetRandomGeneratorOfTheQuadraticResidue(t *testing.T) { + // Use a small safe-prime product: p=5 (q=2), p2=7 (q2=3), N=35 + // This is tiny but exercises the code path. + n := big.NewInt(35) + g := GetRandomGeneratorOfTheQuadraticResidue(rand.Reader, n) + if g == nil { + t.Fatal("returned nil") + } + if g.Sign() <= 0 || g.Cmp(n) >= 0 { + t.Fatalf("out of range: %v", g) + } +} + +func TestGetRandomQuadraticNonResidue(t *testing.T) { + n := big.NewInt(35) + w := GetRandomQuadraticNonResidue(rand.Reader, n) + if w == nil { + t.Fatal("returned nil") + } + if big.Jacobi(w, n) != -1 { + t.Fatalf("should have Jacobi -1, got %d", big.Jacobi(w, n)) + } +} + +func TestMustGetRandomIntPanicsBadBits(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("should panic on 0 bits") + } + }() + MustGetRandomInt(rand.Reader, 0) +} + +func TestGetRandomPrimeInt(t *testing.T) { + p := GetRandomPrimeInt(rand.Reader, 64) + if p == nil { + t.Fatal("returned nil") + } + if !p.ProbablyPrime(20) { + t.Fatal("not prime") + } +} + +func TestIsNumberInMultiplicativeGroup(t *testing.T) { + n := big.NewInt(15) + if !IsNumberInMultiplicativeGroup(n, big.NewInt(7)) { + t.Fatal("7 should be in Z*_15") + } + if IsNumberInMultiplicativeGroup(n, big.NewInt(3)) { + t.Fatal("3 should NOT be in Z*_15 (gcd=3)") + } + if IsNumberInMultiplicativeGroup(n, big.NewInt(0)) { + t.Fatal("0 should NOT be in Z*_15") + } + if IsNumberInMultiplicativeGroup(n, big.NewInt(-1)) { + t.Fatal("negative should NOT be in Z*_15") + } +} + +// --- safe_prime.go --- + +func TestGermainSafePrimeAccessors(t *testing.T) { + // q=11 is prime, p = 2*11+1 = 23 is also prime → safe prime pair + q := big.NewInt(11) + p := big.NewInt(23) + gsp := &GermainSafePrime{q: q, p: p} + + if gsp.Prime().Cmp(q) != 0 { + t.Fatal("Prime() mismatch") + } + if gsp.SafePrime().Cmp(p) != 0 { + t.Fatal("SafePrime() mismatch") + } + if !gsp.Validate() { + t.Fatal("valid safe prime should pass Validate()") + } +} + +// --- hash.go --- + +func TestSHA512_256iOne(t *testing.T) { + h := SHA512_256iOne(big.NewInt(42)) + if h == nil { + t.Fatal("returned nil") + } + if h.Sign() <= 0 { + t.Fatal("hash should be positive") + } + + // Nil input returns nil + h2 := SHA512_256iOne(nil) + if h2 != nil { + t.Fatal("nil input should return nil") + } +} diff --git a/tss-lib/common/hash.go b/tss-lib/common/hash.go index 2ffcec1..266b3a3 100644 --- a/tss-lib/common/hash.go +++ b/tss-lib/common/hash.go @@ -1,16 +1,16 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package common import ( "crypto" - _ "crypto/sha512" "encoding/binary" "math/big" + + _ "crypto/sha512" ) const ( @@ -20,7 +20,6 @@ const ( // SHA-512/256 is protected against length extension attacks and is more performant than SHA-256 on 64-bit architectures. // https://en.wikipedia.org/wiki/Template:Comparison_of_SHA_functions func SHA512_256(in ...[]byte) []byte { - var data []byte state := crypto.SHA512_256.New() inLen := len(in) if inLen == 0 { @@ -36,7 +35,7 @@ func SHA512_256(in ...[]byte) []byte { bzSize += len(bz) } dataCap := len(inLenBz) + bzSize + inLen + (inLen * 8) - data = make([]byte, 0, dataCap) + data := make([]byte, 0, dataCap) data = append(data, inLenBz...) for _, bz := range in { data = append(data, bz...) @@ -56,7 +55,6 @@ func SHA512_256(in ...[]byte) []byte { } func SHA512_256i(in ...*big.Int) *big.Int { - var data []byte state := crypto.SHA512_256.New() inLen := len(in) if inLen == 0 { @@ -70,11 +68,18 @@ func SHA512_256i(in ...*big.Int) *big.Int { binary.LittleEndian.PutUint64(inLenBz, uint64(inLen)) ptrs := make([][]byte, inLen) for i, n := range in { - ptrs[i] = n.Bytes() + // [FORK] Nil guard: upstream panics on nil big.Int input. Protocol fields + // (e.g., optional SSID components) may legitimately be nil; we hash the + // encoding of zero instead, matching the behaviour of big.NewInt(0).Bytes(). + if n == nil { + ptrs[i] = zero.Bytes() + } else { + ptrs[i] = n.Bytes() + } bzSize += len(ptrs[i]) } dataCap := len(inLenBz) + bzSize + inLen + (inLen * 8) - data = make([]byte, 0, dataCap) + data := make([]byte, 0, dataCap) data = append(data, inLenBz...) for i := range in { data = append(data, ptrs[i]...) @@ -93,10 +98,12 @@ func SHA512_256i(in ...*big.Int) *big.Int { return new(big.Int).SetBytes(state.Sum(nil)) } -// SHA512_256i_TAGGED tagged version of SHA512_256i +// SHA512_256i_TAGGED implements a tagged hash (double-prefix construction per BIP-340) +// for SSID domain separation. All proof constructors/verifiers pass Session tags through +// this function to bind proofs to a specific ceremony session, preventing cross-ceremony +// replay attacks. func SHA512_256i_TAGGED(tag []byte, in ...*big.Int) *big.Int { tagBz := SHA512_256(tag) - var data []byte state := crypto.SHA512_256.New() state.Write(tagBz) state.Write(tagBz) @@ -112,6 +119,7 @@ func SHA512_256i_TAGGED(tag []byte, in ...*big.Int) *big.Int { binary.LittleEndian.PutUint64(inLenBz, uint64(inLen)) ptrs := make([][]byte, inLen) for i, n := range in { + // Nil guard (same as SHA512_256i above, present in both upstream and fork). if n == nil { ptrs[i] = zero.Bytes() } else { @@ -120,7 +128,7 @@ func SHA512_256i_TAGGED(tag []byte, in ...*big.Int) *big.Int { bzSize += len(ptrs[i]) } dataCap := len(inLenBz) + bzSize + inLen + (inLen * 8) - data = make([]byte, 0, dataCap) + data := make([]byte, 0, dataCap) data = append(data, inLenBz...) for i := range in { data = append(data, ptrs[i]...) @@ -140,12 +148,11 @@ func SHA512_256i_TAGGED(tag []byte, in ...*big.Int) *big.Int { } func SHA512_256iOne(in *big.Int) *big.Int { - var data []byte state := crypto.SHA512_256.New() if in == nil { return nil } - data = in.Bytes() + data := in.Bytes() // n < len(data) or an error will never happen. // see: https://golang.org/pkg/hash/#Hash and https://github.com/golang/go/wiki/Hashing#the-hashhash-interface if _, err := state.Write(data); err != nil { diff --git a/tss-lib/common/hash_kat_test.go b/tss-lib/common/hash_kat_test.go new file mode 100644 index 0000000..7c923f6 --- /dev/null +++ b/tss-lib/common/hash_kat_test.go @@ -0,0 +1,74 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package common + +import ( + "encoding/hex" + "math/big" + "testing" +) + +// TestSHA512_256KnownAnswer pins SHA512_256 output to a known digest. +// If the function is replaced with a stub (e.g. returning a constant), +// this test fails immediately. +// +// The expected value was computed from the production implementation +// and captures the length-prefixed, delimited internal format. +func TestSHA512_256KnownAnswer(t *testing.T) { + got := hex.EncodeToString(SHA512_256([]byte("abc"))) + const want = "decbe7e7d33a897617c3f6fbe553c3598f786a93a2c4237f3dcdd2c8dd817532" + if got != want { + t.Fatalf("SHA512_256(\"abc\"):\n got: %s\n want: %s", got, want) + } +} + +// TestSHA512_256iKnownAnswer pins SHA512_256i to a known digest. +func TestSHA512_256iKnownAnswer(t *testing.T) { + got := SHA512_256i(big.NewInt(42), big.NewInt(99)) + const want = "3bc659aa5672f076492e3c116fbd036134244f5178b07b8441a149708f929942" + if hex.EncodeToString(got.Bytes()) != want { + t.Fatalf("SHA512_256i(42, 99): got %x, want %s", got, want) + } +} + +// TestSHA512_256iOneKnownAnswer pins SHA512_256iOne to a known digest. +func TestSHA512_256iOneKnownAnswer(t *testing.T) { + got := SHA512_256iOne(big.NewInt(12345)) + const want = "795c165105ac2e5c09cc7a734a82c95b7ce8f870a48e419737150a2eb8c0520b" + if hex.EncodeToString(got.Bytes()) != want { + t.Fatalf("SHA512_256iOne(12345): got %x, want %s", got, want) + } +} + +// TestSHA512_256TAGGEDDomainSeparation verifies the tagged hash +// produces a different digest than the untagged variant, and is +// deterministic. +func TestSHA512_256TAGGEDDomainSeparation(t *testing.T) { + tag := []byte("test-domain") + input := big.NewInt(77) + + tagged := SHA512_256i_TAGGED(tag, input) + untagged := SHA512_256i(input) + + if tagged.Cmp(untagged) == 0 { + t.Fatal("tagged and untagged hash must differ") + } + + // Deterministic. + tagged2 := SHA512_256i_TAGGED(tag, input) + if tagged.Cmp(tagged2) != 0 { + t.Fatal("tagged hash is not deterministic") + } +} + +// TestSHA512_256Collision verifies distinct inputs produce distinct +// hashes. A stub returning a constant fails this. +func TestSHA512_256Collision(t *testing.T) { + a := hex.EncodeToString(SHA512_256([]byte("input one"))) + b := hex.EncodeToString(SHA512_256([]byte("input two"))) + if a == b { + t.Fatal("distinct inputs must produce distinct hashes") + } +} diff --git a/tss-lib/common/hash_test.go b/tss-lib/common/hash_test.go new file mode 100644 index 0000000..8db3a7b --- /dev/null +++ b/tss-lib/common/hash_test.go @@ -0,0 +1,613 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package common + +import ( + "encoding/hex" + "math/big" + "testing" +) + +// TestSHA512_256iZeroInput documents that big.Int(0).Bytes() returns []byte{}, +// so SHA512_256i(big.Int(0)) hashes an empty-magnitude byte sequence. +// Rust implementations MUST match this behavior: use [] (empty) not [0x00]. +func TestSHA512_256iZeroInput(t *testing.T) { + result := SHA512_256i(big.NewInt(0)) + if result == nil { + t.Fatal("SHA512_256i(0) should not return nil") + } + h := hex.EncodeToString(result.Bytes()) + t.Logf("SHA512_256i(0) = %s", h) + + // Verify it differs from SHA512_256i(1). + result1 := SHA512_256i(big.NewInt(1)) + if result.Cmp(result1) == 0 { + t.Fatal("SHA512_256i(0) should differ from SHA512_256i(1)") + } +} + +// TestSHA512_256iMultipleWithZero documents the preimage when zero is one +// of multiple arguments. +func TestSHA512_256iMultipleWithZero(t *testing.T) { + // SHA512_256i(2, 0) vs SHA512_256i(2, 1). + r20 := SHA512_256i(big.NewInt(2), big.NewInt(0)) + r21 := SHA512_256i(big.NewInt(2), big.NewInt(1)) + if r20.Cmp(r21) == 0 { + t.Fatal("SHA512_256i(2,0) should differ from SHA512_256i(2,1)") + } + t.Logf("SHA512_256i(2, 0) = %s", hex.EncodeToString(r20.Bytes())) + t.Logf("SHA512_256i(2, 1) = %s", hex.EncodeToString(r21.Bytes())) + + // SHA512_256i(1, 0) vs SHA512_256i(0, 1). + r10 := SHA512_256i(big.NewInt(1), big.NewInt(0)) + r01 := SHA512_256i(big.NewInt(0), big.NewInt(1)) + if r10.Cmp(r01) == 0 { + t.Fatal("SHA512_256i(1,0) should differ from SHA512_256i(0,1)") + } + t.Logf("SHA512_256i(1, 0) = %s", hex.EncodeToString(r10.Bytes())) + t.Logf("SHA512_256i(0, 1) = %s", hex.EncodeToString(r01.Bytes())) +} + +// TestSHA512_256iEmpty verifies nil return for empty input. +func TestSHA512_256iEmpty(t *testing.T) { + result := SHA512_256i() + if result != nil { + t.Fatal("SHA512_256i() with no args should return nil") + } +} + +// TestSHA512_256iOneVsSHA512_256i documents that SHA512_256iOne and +// SHA512_256i produce DIFFERENT results for the same input. The Rust +// guest must implement both functions. +func TestSHA512_256iOneVsSHA512_256i(t *testing.T) { + x := big.NewInt(42) + + resultOne := SHA512_256iOne(x) + resultI := SHA512_256i(x) + + if resultOne.Cmp(resultI) == 0 { + t.Fatal("SHA512_256iOne(42) should differ from SHA512_256i(42)") + } + // Hardcoded golden vectors — Rust must match exactly. + expectOne := "4c443fc75eff4e3c217c1a216d2a18a4057ca05a1a4098d147b0f28a5453c7c8" + expectI := "5d9ba0bb5fd6df1e69b641f81290de5b7aa24905172b02aee8d39157253814a6" + gotOne := hex.EncodeToString(resultOne.Bytes()) + gotI := hex.EncodeToString(resultI.Bytes()) + if gotOne != expectOne { + t.Fatalf("SHA512_256iOne(42) = %s, want %s", gotOne, expectOne) + } + if gotI != expectI { + t.Fatalf("SHA512_256i(42) = %s, want %s", gotI, expectI) + } +} + +// TestSHA512_256iOneZero documents SHA512_256iOne behavior with zero. +func TestSHA512_256iOneZero(t *testing.T) { + result := SHA512_256iOne(big.NewInt(0)) + if result == nil { + t.Fatal("SHA512_256iOne(0) should not return nil") + } + // SHA512_256iOne(0) = SHA512/256("") — well-known empty-string hash. + expect := "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a" + got := hex.EncodeToString(result.Bytes()) + if got != expect { + t.Fatalf("SHA512_256iOne(0) = %s, want %s", got, expect) + } + + // SHA512_256iOne(0) hashes empty bytes (since big.Int(0).Bytes() = []). + // This is identical to SHA512/256("") which is a well-known value. + result1 := SHA512_256iOne(big.NewInt(1)) + if result.Cmp(result1) == 0 { + t.Fatal("SHA512_256iOne(0) should differ from SHA512_256iOne(1)") + } +} + +// TestSHA512_256iOneNil documents nil behavior. +func TestSHA512_256iOneNil(t *testing.T) { + result := SHA512_256iOne(nil) + if result != nil { + t.Fatal("SHA512_256iOne(nil) should return nil") + } +} + +// TestSHA512_256iNilElementHandled documents that SHA512_256i substitutes +// zero.Bytes() for nil *big.Int elements, matching the tagged variant behavior. +func TestSHA512_256iNilElementHandled(t *testing.T) { + // Must not panic — nil elements are substituted with zero. + resultNil := SHA512_256i(big.NewInt(1), nil, big.NewInt(2)) + resultZero := SHA512_256i(big.NewInt(1), big.NewInt(0), big.NewInt(2)) + if resultNil == nil { + t.Fatal("expected non-nil result") + } + if resultNil.Cmp(resultZero) != 0 { + t.Fatal("SHA512_256i with nil and 0 should produce the same result") + } +} + +// TestSHA512_256iNegativeInput documents that big.Int.Bytes() drops the sign, +// so SHA512_256i(-1) produces the same hash as SHA512_256i(1). +func TestSHA512_256iNegativeInput(t *testing.T) { + hashPos := SHA512_256i(big.NewInt(1)) + hashNeg := SHA512_256i(big.NewInt(-1)) + if hashPos.Cmp(hashNeg) != 0 { + t.Fatal("SHA512_256i(-1) should equal SHA512_256i(1) because Bytes() drops sign") + } +} + +// TestSHA512_256iTaggedNilElement documents that the tagged variant substitutes +// zero.Bytes() for nil inputs (the untagged variant now does the same). +func TestSHA512_256iTaggedNilElement(t *testing.T) { + tag := []byte("test-tag") + + // Tagged version handles nil by substituting zero. + resultNil := SHA512_256i_TAGGED(tag, nil) + resultZero := SHA512_256i_TAGGED(tag, big.NewInt(0)) + + // Since zero.Bytes() == big.NewInt(0).Bytes() == []byte{}, these should match. + if resultNil.Cmp(resultZero) != 0 { + t.Fatal("TAGGED with nil and TAGGED with 0 should produce the same result") + } + t.Logf("SHA512_256i_TAGGED('test-tag', nil) = %s", hex.EncodeToString(resultNil.Bytes())) + t.Logf("SHA512_256i_TAGGED('test-tag', 0) = %s", hex.EncodeToString(resultZero.Bytes())) +} + +// TestSHA512_256iTaggedVsUntagged documents that tagged and untagged produce +// different results for the same input. +func TestSHA512_256iTaggedVsUntagged(t *testing.T) { + tag := []byte("session") + x := big.NewInt(42) + + tagged := SHA512_256i_TAGGED(tag, x) + untagged := SHA512_256i(x) + + if tagged.Cmp(untagged) == 0 { + t.Fatal("tagged and untagged should differ") + } +} + +// TestSHA512_256iGoldenVectors produces hardcoded golden vectors for +// cross-language verification. These exact hex values must be reproduced +// by any Rust implementation. +func TestSHA512_256iGoldenVectors(t *testing.T) { + tests := []struct { + name string + inputs []*big.Int + expected string // hardcoded hex — Rust must match exactly + }{ + {"single_1", []*big.Int{big.NewInt(1)}, "c272488e6eb0653d5dd36405b8525c31058d6bcb56a8326e037605aa70c219a8"}, + {"single_0", []*big.Int{big.NewInt(0)}, "bbbbf79af6a54ebfd64b703fca4241d1ef2930bd8fcd0c898da64eeac240fe24"}, + {"pair_1_2", []*big.Int{big.NewInt(1), big.NewInt(2)}, "bb744ef1d81d80add983c0ee6058621cb9de243f8e99c7eb16c816bbbd4c7dca"}, + {"pair_0_0", []*big.Int{big.NewInt(0), big.NewInt(0)}, "ccc267e9748792ad0ab7632b3674208462cd56b5453c014d4f7844bfd3f9be5c"}, + {"triple_0_1_2", []*big.Int{big.NewInt(0), big.NewInt(1), big.NewInt(2)}, "09c0eac3208b7cb3a48f32e33e7003d5df98f4ee7f9fa797687610b78e082407"}, + {"large_256", []*big.Int{big.NewInt(256)}, "c1f31d55168ae2cabfa0909fbdd93d248ff8e60386387aef08908bff718f4eb5"}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := SHA512_256i(tc.inputs...) + if result == nil { + t.Fatal("expected non-nil result") + } + got := hex.EncodeToString(result.Bytes()) + // Pad to 64 hex chars (32 bytes) to match %064x format. + for len(got) < 64 { + got = "0" + got + } + if got != tc.expected { + t.Fatalf("SHA512_256i(%s) = %s, want %s", tc.name, got, tc.expected) + } + }) + } +} + +// TestBigIntBytesEncodingForHash documents the critical Go big.Int.Bytes() +// encoding behavior that affects all hash computations. +func TestBigIntBytesEncodingForHash(t *testing.T) { + tests := []struct { + value int64 + expected string // hex + }{ + {0, ""}, // empty! Rust BigUint::to_bytes_be() returns [0x00] instead + {1, "01"}, + {127, "7f"}, + {128, "80"}, + {255, "ff"}, + {256, "0100"}, + {65535, "ffff"}, + {65536, "010000"}, + } + for _, tc := range tests { + got := hex.EncodeToString(big.NewInt(tc.value).Bytes()) + if got != tc.expected { + t.Errorf("big.Int(%d).Bytes() = %q, want %q", tc.value, got, tc.expected) + } + } +} + +// TestAppendBigIntToBytesSlicePartyZero verifies that the length-prefixed +// encoding makes party 0 distinct from bare SSID. Party 0 gets a 4-byte +// length prefix [00 00 00 00] appended (length=0, no value bytes). +func TestAppendBigIntToBytesSlicePartyZero(t *testing.T) { + ssid := []byte("test-ssid-32-bytes-for-testing!!") + + ctx0 := AppendBigIntToBytesSlice(ssid, big.NewInt(0)) + ctx1 := AppendBigIntToBytesSlice(ssid, big.NewInt(1)) + + // Party 0 gets ssid + [00 00 00 00] (4-byte length prefix, zero-length value). + if len(ctx0) != len(ssid)+4 { + t.Fatalf("party 0 context should be ssid+4: got %d, want %d", + len(ctx0), len(ssid)+4) + } + // Party 1 gets ssid + [00 00 00 01] + [01] (4-byte length=1, value=0x01). + if len(ctx1) != len(ssid)+5 { + t.Fatalf("party 1 context should be ssid+5: got %d, want %d", + len(ctx1), len(ssid)+5) + } + + // Party 0 and party 1 differ. + if hex.EncodeToString(ctx0) == hex.EncodeToString(ctx1) { + t.Fatal("party 0 and party 1 contexts should differ") + } + + // Party 0 is now DISTINCT from bare ssid. + if hex.EncodeToString(ctx0) == hex.EncodeToString(ssid) { + t.Fatal("party 0 context should differ from bare ssid after length-prefix fix") + } +} + +// TestAppendBigIntToBytesSliceGoldenVectors verifies hardcoded hex golden +// vectors for known inputs. Rust implementations must match exactly. +func TestAppendBigIntToBytesSliceGoldenVectors(t *testing.T) { + ssid := []byte("test-ssid") + + tests := []struct { + name string + index int64 + expected string + }{ + // ssid bytes + [00 00 00 00] (length=0, no value bytes for zero) + {"index_0", 0, "746573742d7373696400000000"}, + // ssid bytes + [00 00 00 01] + [01] + {"index_1", 1, "746573742d737369640000000101"}, + // ssid bytes + [00 00 00 01] + [ff] + {"index_255", 255, "746573742d7373696400000001ff"}, + // ssid bytes + [00 00 00 02] + [01 00] + {"index_256", 256, "746573742d73736964000000020100"}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := AppendBigIntToBytesSlice(ssid, big.NewInt(tc.index)) + got := hex.EncodeToString(result) + if got != tc.expected { + t.Fatalf("AppendBigIntToBytesSlice(ssid, %d) = %s, want %s", + tc.index, got, tc.expected) + } + }) + } +} + +// TestAppendBigIntToBytesSliceNegativeInput documents that big.Int.Bytes() +// drops the sign bit, so AppendBigIntToBytesSlice(ssid, -5) produces the +// same result as AppendBigIntToBytesSlice(ssid, 5). Rust implementations +// using unsigned types will naturally match this behavior. +func TestAppendBigIntToBytesSliceNegativeInput(t *testing.T) { + ssid := []byte("test-ssid") + pos := AppendBigIntToBytesSlice(ssid, big.NewInt(5)) + neg := AppendBigIntToBytesSlice(ssid, big.NewInt(-5)) + if hex.EncodeToString(pos) != hex.EncodeToString(neg) { + t.Fatalf("negative and positive should match: pos=%s neg=%s", + hex.EncodeToString(pos), hex.EncodeToString(neg)) + } +} + +// TestAppendBigIntToBytesSliceNilCommonBytes verifies that passing nil as +// commonBytes works correctly and produces only the length prefix + value. +func TestAppendBigIntToBytesSliceNilCommonBytes(t *testing.T) { + result := AppendBigIntToBytesSlice(nil, big.NewInt(42)) + got := hex.EncodeToString(result) + // 42 = 0x2a, length = 1 byte → [00 00 00 01] [2a] + expected := "000000012a" + if got != expected { + t.Fatalf("AppendBigIntToBytesSlice(nil, 42) = %s, want %s", got, expected) + } +} + +// TestAppendBigIntToBytesSliceMultipleAppends verifies that the function does +// not mutate the input commonBytes slice. The implementation allocates a new +// slice rather than appending in-place. +func TestAppendBigIntToBytesSliceMultipleAppends(t *testing.T) { + ssid := []byte("test") + ssidCopy := make([]byte, len(ssid)) + copy(ssidCopy, ssid) + + _ = AppendBigIntToBytesSlice(ssid, big.NewInt(42)) + + // ssid should still equal ssidCopy — no mutation. + if hex.EncodeToString(ssid) != hex.EncodeToString(ssidCopy) { + t.Fatalf("AppendBigIntToBytesSlice mutated input: was %s, now %s", + hex.EncodeToString(ssidCopy), hex.EncodeToString(ssid)) + } +} + +// TestAppendBigIntToBytesSliceLengthPrefixIs4Bytes verifies that for various +// indices, the 4 bytes immediately after the ssid are always exactly a +// big-endian uint32 length prefix encoding the byte length of the index value. +func TestAppendBigIntToBytesSliceLengthPrefixIs4Bytes(t *testing.T) { + ssid := []byte("test-ssid") + ssidLen := len(ssid) + + tests := []struct { + index int64 + expectedLen uint32 // expected value of the 4-byte length prefix + expectedBytes int // expected byte length of the big.Int value + }{ + {0, 0, 0}, // big.NewInt(0).Bytes() = [] + {1, 1, 1}, // big.NewInt(1).Bytes() = [0x01] + {256, 2, 2}, // big.NewInt(256).Bytes() = [0x01, 0x00] + {65536, 3, 3}, // big.NewInt(65536).Bytes() = [0x01, 0x00, 0x00] + } + for _, tc := range tests { + result := AppendBigIntToBytesSlice(ssid, big.NewInt(tc.index)) + + // Extract the 4-byte length prefix immediately after ssid. + if len(result) < ssidLen+4 { + t.Fatalf("index %d: result too short: %d", tc.index, len(result)) + } + prefix := result[ssidLen : ssidLen+4] + gotLen := uint32(prefix[0])<<24 | uint32(prefix[1])<<16 | uint32(prefix[2])<<8 | uint32(prefix[3]) + if gotLen != tc.expectedLen { + t.Fatalf("index %d: length prefix = %d, want %d (bytes: %s)", + tc.index, gotLen, tc.expectedLen, hex.EncodeToString(prefix)) + } + + // Total length should be ssid + 4 (prefix) + expectedBytes (value). + expectedTotal := ssidLen + 4 + tc.expectedBytes + if len(result) != expectedTotal { + t.Fatalf("index %d: total length = %d, want %d", + tc.index, len(result), expectedTotal) + } + } +} + +// TestSHA512_256iTaggedGoldenVectors freezes golden vectors for +// SHA512_256i_TAGGED. These exact hex values must be reproduced by any +// Rust implementation. +func TestSHA512_256iTaggedGoldenVectors(t *testing.T) { + tests := []struct { + name string + tag []byte + inputs []*big.Int + expected string + }{ + { + "session_0_1", + []byte("session"), + []*big.Int{big.NewInt(0), big.NewInt(1)}, + "73b9c44658bea960ae093eba82e8190bcd989b18c8e6a87e03aa6521ebd5ccfc", + }, + { + "session_42", + []byte("session"), + []*big.Int{big.NewInt(42)}, + "c1fd4c4302095795a413cd26f03b31a2f04dbb7d845478fb0fbe88bd114303db", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := SHA512_256i_TAGGED(tc.tag, tc.inputs...) + if result == nil { + t.Fatal("expected non-nil result") + } + got := hex.EncodeToString(result.Bytes()) + if got != tc.expected { + t.Fatalf("SHA512_256i_TAGGED(%s) = %s, want %s", + tc.name, got, tc.expected) + } + }) + } +} + +// TestAppendBigIntToBytesSliceNilAppended verifies that passing nil as the +// appended *big.Int does not panic and produces the same result as passing +// big.NewInt(0) — both append only a 4-byte zero-length prefix. +func TestAppendBigIntToBytesSliceNilAppended(t *testing.T) { + ssid := []byte("test-ssid") + + // Must not panic. + result := AppendBigIntToBytesSlice(ssid, nil) + + // Should produce the same encoding as big.NewInt(0): ssid + [00 00 00 00]. + expected := AppendBigIntToBytesSlice(ssid, big.NewInt(0)) + if hex.EncodeToString(result) != hex.EncodeToString(expected) { + t.Fatalf("nil and zero should produce identical encoding: nil=%s, zero=%s", + hex.EncodeToString(result), hex.EncodeToString(expected)) + } + + // Total length: ssid(9) + prefix(4) = 13. + if len(result) != len(ssid)+4 { + t.Fatalf("expected length %d, got %d", len(ssid)+4, len(result)) + } +} + +// TestAppendBigIntToBytesSliceBothNil verifies that passing nil for both +// commonBytes and appended works correctly. +func TestAppendBigIntToBytesSliceBothNil(t *testing.T) { + result := AppendBigIntToBytesSlice(nil, nil) + // Should be just [00 00 00 00]. + expected := "00000000" + got := hex.EncodeToString(result) + if got != expected { + t.Fatalf("AppendBigIntToBytesSlice(nil, nil) = %s, want %s", got, expected) + } +} + +// --------------------------------------------------------------------------- +// ContextI/ContextJ regression tests +// +// These tests freeze the exact byte encoding of ContextI and ContextJ as +// constructed in the round files: +// - eddsa/keygen/round_2.go (line 50) +// - eddsa/signing/round_2.go (line 37) +// - ecdsa/signing/round_3.go (line 41) +// +// All three construct: AppendBigIntToBytesSlice(ssid, big.Int(partyIndex)) +// +// The OLD encoding (bare append) produced: ssid || big.Int(i).Bytes() +// - For index 0: ssid (UNCHANGED — indistinguishable from bare SSID) +// - For index 1: ssid || [0x01] +// +// The NEW encoding (length-prefixed) produces: ssid || [4-byte len] || big.Int(i).Bytes() +// - For index 0: ssid || [00 00 00 00] (distinguishable from bare SSID) +// - For index 1: ssid || [00 00 00 01] || [0x01] +// +// If someone reverts the fix in any round file back to bare append, the E2E +// tests would still pass (all parties use the same encoding). These tests +// catch the regression by freezing the CORRECT encoding as golden vectors. +// --------------------------------------------------------------------------- + +// TestContextIEncodingRegressionPartyZero verifies that the ContextI encoding +// for party index 0 differs from bare SSID. This is the critical regression +// test: with the old bare-append encoding, party 0 got ContextI == SSID +// (because big.Int(0).Bytes() == []), making party 0's proofs use a +// different session context than all other parties. +func TestContextIEncodingRegressionPartyZero(t *testing.T) { + ssid := []byte("test-ssid-32-bytes-for-testing!!") + + // NEW encoding (correct): ssid + [00 00 00 00] + contextI := AppendBigIntToBytesSlice(ssid, new(big.Int).SetUint64(0)) + + // OLD encoding (buggy): ssid + big.Int(0).Bytes() = ssid + [] = ssid + oldContextI := append([]byte{}, ssid...) + oldContextI = append(oldContextI, new(big.Int).SetUint64(0).Bytes()...) + + // The new encoding MUST differ from the old encoding. + if hex.EncodeToString(contextI) == hex.EncodeToString(oldContextI) { + t.Fatal("ContextI for party 0 must differ from bare SSID — " + + "if this fails, the AppendBigIntToBytesSlice fix has been reverted") + } + + // The new encoding must be exactly 4 bytes longer (the length prefix). + if len(contextI) != len(ssid)+4 { + t.Fatalf("ContextI for party 0 should be ssid+4 bytes, got %d", len(contextI)) + } + + // Verify the 4-byte suffix is [00 00 00 00] (zero-length value). + suffix := contextI[len(ssid):] + expectedSuffix := "00000000" + if hex.EncodeToString(suffix) != expectedSuffix { + t.Fatalf("ContextI suffix for party 0 = %s, want %s", + hex.EncodeToString(suffix), expectedSuffix) + } +} + +// TestContextIEncodingRegressionPartyOne verifies that party 1's ContextI +// uses the length-prefixed encoding, not bare append. +func TestContextIEncodingRegressionPartyOne(t *testing.T) { + ssid := []byte("test-ssid-32-bytes-for-testing!!") + + // NEW encoding (correct): ssid + [00 00 00 01] + [01] + contextI := AppendBigIntToBytesSlice(ssid, new(big.Int).SetUint64(1)) + + // OLD encoding (buggy): ssid + [01] + oldContextI := append([]byte{}, ssid...) + oldContextI = append(oldContextI, new(big.Int).SetUint64(1).Bytes()...) + + // The new encoding is 4 bytes longer (the length prefix). + if len(contextI) != len(oldContextI)+4 { + t.Fatalf("new encoding should be 4 bytes longer: new=%d, old=%d", + len(contextI), len(oldContextI)) + } + + // Verify exact encoding. + expectedSuffix := "0000000101" // [00 00 00 01] + [01] + gotSuffix := hex.EncodeToString(contextI[len(ssid):]) + if gotSuffix != expectedSuffix { + t.Fatalf("ContextI suffix for party 1 = %s, want %s", gotSuffix, expectedSuffix) + } +} + +// TestContextIEncodingDistinguishesAllParties verifies that each party index +// 0-4 gets a unique ContextI encoding with the length-prefixed format. +func TestContextIEncodingDistinguishesAllParties(t *testing.T) { + ssid := []byte("test-ssid-32-bytes-for-testing!!") + + seen := make(map[string]int) + for i := 0; i < 5; i++ { + contextI := AppendBigIntToBytesSlice(ssid, new(big.Int).SetInt64(int64(i))) + h := hex.EncodeToString(contextI) + if prev, exists := seen[h]; exists { + t.Fatalf("party %d has same ContextI as party %d: %s", i, prev, h) + } + seen[h] = i + } + + // Also verify party 0 differs from bare SSID. + if _, exists := seen[hex.EncodeToString(ssid)]; exists { + t.Fatal("a party's ContextI collides with bare SSID") + } +} + +// TestContextIGoldenVectors freezes the exact hex encoding of ContextI for +// party indices 0-2 with a known SSID. Rust implementations MUST reproduce +// these exact bytes. If the encoding in any round file is reverted to bare +// append, these vectors will no longer match the round's actual output. +func TestContextIGoldenVectors(t *testing.T) { + ssid := []byte("test-ssid") + + tests := []struct { + index uint64 + expected string // hex of full ContextI + }{ + // ssid("test-ssid") = 746573742d73736964 + // index 0: ssid + [00 00 00 00] + {0, "746573742d7373696400000000"}, + // index 1: ssid + [00 00 00 01] + [01] + {1, "746573742d737369640000000101"}, + // index 2: ssid + [00 00 00 01] + [02] + {2, "746573742d737369640000000102"}, + } + for _, tc := range tests { + contextI := AppendBigIntToBytesSlice(ssid, new(big.Int).SetUint64(tc.index)) + got := hex.EncodeToString(contextI) + if got != tc.expected { + t.Fatalf("ContextI(ssid, %d) = %s, want %s", tc.index, got, tc.expected) + } + } +} + +// TestSHA512_256iDomainSeparationLengthPrefix verifies that SHA512_256i(256) +// differs from SHA512_256i(1, 0) even though both have magnitude bytes +// [0x01, 0x00]. The length prefix and block count in the hash preimage +// ensure proper domain separation. +func TestSHA512_256iDomainSeparationLengthPrefix(t *testing.T) { + // big.NewInt(256).Bytes() = [0x01, 0x00] + // big.NewInt(1).Bytes() = [0x01], big.NewInt(0).Bytes() = [] + // Without domain separation, the concatenation of magnitudes could collide. + h256 := SHA512_256i(big.NewInt(256)) + h10 := SHA512_256i(big.NewInt(1), big.NewInt(0)) + + if h256.Cmp(h10) == 0 { + t.Fatal("SHA512_256i(256) should differ from SHA512_256i(1, 0) — " + + "domain separation via block count and length prefixes must prevent collision") + } + + // Freeze golden vectors for cross-language verification. + expect256 := "c1f31d55168ae2cabfa0909fbdd93d248ff8e60386387aef08908bff718f4eb5" + expect10 := "16e94de4c1997dce6279e7d4c576f9e55f26071515032945a60bb085e38d03e1" + got256 := hex.EncodeToString(h256.Bytes()) + got10 := hex.EncodeToString(h10.Bytes()) + // Pad to 64 hex chars (32 bytes). + for len(got256) < 64 { + got256 = "0" + got256 + } + for len(got10) < 64 { + got10 = "0" + got10 + } + if got256 != expect256 { + t.Fatalf("SHA512_256i(256) = %s, want %s", got256, expect256) + } + if got10 != expect10 { + t.Fatalf("SHA512_256i(1, 0) = %s, want %s", got10, expect10) + } +} diff --git a/tss-lib/common/hash_utils.go b/tss-lib/common/hash_utils.go index 4fd2619..a85ebd7 100644 --- a/tss-lib/common/hash_utils.go +++ b/tss-lib/common/hash_utils.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package common @@ -10,9 +9,17 @@ import ( "math/big" ) -// RejectionSample implements the rejection sampling logic for converting a -// SHA512/256 hash to a value between 0-q +// RejectionSample converts a hash output to a value in [0, q). +// +// Despite its name, this is modular reduction (hash mod q), not true +// rejection sampling. The statistical distance from uniform is at most +// (2^hashBits mod q) / 2^hashBits. For SHA-512/256 (256-bit output) and +// secp256k1 (q ≈ 2^256), the bias is ≈ 2^-128 — within standard +// Fiat-Shamir security bounds. For larger moduli (e.g., 2048-bit N in +// ModProof), the bias is negligible. +// [FORK] Upstream mutates eHash in-place (eHash.Mod(eHash, q)), which is an +// aliasing bug: callers that retain a reference to eHash see it silently +// modified. We allocate a new big.Int to avoid this side effect. func RejectionSample(q *big.Int, eHash *big.Int) *big.Int { // e' = eHash - e := eHash.Mod(eHash, q) - return e + return new(big.Int).Mod(eHash, q) } diff --git a/tss-lib/common/hash_utils_test.go b/tss-lib/common/hash_utils_test.go index c56b8f2..51a8094 100644 --- a/tss-lib/common/hash_utils_test.go +++ b/tss-lib/common/hash_utils_test.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package common_test @@ -12,9 +11,29 @@ import ( "reflect" "testing" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) +// TestRejectionSampleMutatesInput verifies that RejectionSample does NOT +// mutate its eHash argument (the in-place mutation bug has been fixed). +func TestRejectionSampleMutatesInput(t *testing.T) { + q := big.NewInt(100) + original := big.NewInt(257) + originalCopy := new(big.Int).Set(original) + + result := common.RejectionSample(q, original) + + // Result is 257 mod 100 = 57. + if result.Cmp(big.NewInt(57)) != 0 { + t.Fatalf("expected 57, got %s", result) + } + + // Verify the input was NOT mutated (fixed from the original in-place mutation bug). + if original.Cmp(originalCopy) != 0 { + t.Fatalf("RejectionSample mutated input: was %s, now %s", originalCopy, original) + } +} + func TestRejectionSample(t *testing.T) { curveQ := common.GetRandomPrimeInt(rand.Reader, 256) randomQ := common.MustGetRandomInt(rand.Reader, 64) @@ -61,3 +80,74 @@ func TestRejectionSample(t *testing.T) { }) } } + +// TestRejectionSampleDoesNotMutateQ verifies that RejectionSample does not +// mutate the q argument. +func TestRejectionSampleDoesNotMutateQ(t *testing.T) { + q := big.NewInt(100) + qCopy := new(big.Int).Set(q) + + common.RejectionSample(q, big.NewInt(257)) + + if q.Cmp(qCopy) != 0 { + t.Fatalf("RejectionSample mutated q: was %s, now %s", qCopy, q) + } +} + +// TestRejectionSampleQEqualsOne verifies that when q=1, the result is always +// 0 because any integer mod 1 = 0. +func TestRejectionSampleQEqualsOne(t *testing.T) { + hashes := []*big.Int{ + big.NewInt(0), + big.NewInt(1), + big.NewInt(12345), + big.NewInt(999999999), + } + for _, hash := range hashes { + result := common.RejectionSample(big.NewInt(1), hash) + if result.Cmp(big.NewInt(0)) != 0 { + t.Fatalf("RejectionSample(1, %s) = %s, want 0", hash, result) + } + } +} + +// TestRejectionSampleResultInRange verifies that for 100 random q values and +// hashes, the result is always in the range [0, q). +func TestRejectionSampleResultInRange(t *testing.T) { + for i := 0; i < 100; i++ { + q := common.MustGetRandomInt(rand.Reader, 128) + // Ensure q > 0 (MustGetRandomInt may return 0 in degenerate cases). + q.Add(q, big.NewInt(1)) + hash := common.MustGetRandomInt(rand.Reader, 256) + + result := common.RejectionSample(q, hash) + + if result.Sign() < 0 { + t.Fatalf("iteration %d: result %s is negative", i, result) + } + if result.Cmp(q) >= 0 { + t.Fatalf("iteration %d: result %s >= q %s", i, result, q) + } + } +} + +// TestRejectionSampleGoldenVector freezes a golden vector for cross-language +// verification. RejectionSample(100, 257) = 257 mod 100 = 57. +func TestRejectionSampleGoldenVector(t *testing.T) { + result := common.RejectionSample(big.NewInt(100), big.NewInt(257)) + if result.Cmp(big.NewInt(57)) != 0 { + t.Fatalf("RejectionSample(100, 257) = %s, want 57", result) + } +} + +// TestRejectionSampleNegativeHash verifies behavior with a negative hash. +// In Go, big.Int.Mod(-257, 100) returns 43 (Go's Mod follows the sign of +// the divisor, returning a non-negative result). Rust implementations +// using unsigned types will need to handle this differently. +func TestRejectionSampleNegativeHash(t *testing.T) { + result := common.RejectionSample(big.NewInt(100), big.NewInt(-257)) + // Go's Mod: -257 mod 100 = 43 (non-negative, follows divisor sign). + if result.Cmp(big.NewInt(43)) != 0 { + t.Fatalf("RejectionSample(100, -257) = %s, want 43", result) + } +} diff --git a/tss-lib/common/int.go b/tss-lib/common/int.go index 54c798c..2498f46 100644 --- a/tss-lib/common/int.go +++ b/tss-lib/common/int.go @@ -1,12 +1,12 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package common import ( + "encoding/binary" "math/big" ) @@ -35,12 +35,6 @@ func (mi *modInt) Sub(x, y *big.Int) *big.Int { return i.Mod(i, mi.i()) } -func (mi *modInt) Div(x, y *big.Int) *big.Int { - i := new(big.Int) - i.Div(x, y) - return i.Mod(i, mi.i()) -} - func (mi *modInt) Mul(x, y *big.Int) *big.Int { i := new(big.Int) i.Mul(x, y) @@ -59,13 +53,36 @@ func (mi *modInt) i() *big.Int { return (*big.Int)(mi) } +// [FORK] Nil guard: upstream panics on nil b or bound. These inputs can be +// attacker-controlled (e.g., received proof fields in ZK verification), so we +// return false instead of crashing. func IsInInterval(b *big.Int, bound *big.Int) bool { + if b == nil || bound == nil { + return false + } return b.Cmp(bound) == -1 && b.Cmp(zero) >= 0 } +// AppendBigIntToBytesSlice appends a length-prefixed big.Int encoding to a +// byte slice. The encoding is [4-byte big-endian length][big.Int.Bytes()]. +// This ensures that big.Int(0) (which has empty Bytes()) is distinguishable +// from "nothing appended" — party index 0 gets [00 00 00 00] appended. +// +// [FORK] Upstream appends raw big.Int.Bytes() without a length prefix, making +// it impossible to distinguish zero-valued fields from absent fields in the +// SSID/CeremonyID byte stream. The length prefix provides unambiguous parsing. func AppendBigIntToBytesSlice(commonBytes []byte, appended *big.Int) []byte { - resultBytes := make([]byte, len(commonBytes), len(commonBytes)+len(appended.Bytes())) + var bz []byte + // Defense-in-depth: all current callers pass non-nil big.Int, but this is a + // public utility function. Guards against future misuse. + if appended != nil { + bz = appended.Bytes() + } + var lenBuf [4]byte + binary.BigEndian.PutUint32(lenBuf[:], uint32(len(bz))) //nolint:gosec // big.Int bytes < 1KB + resultBytes := make([]byte, len(commonBytes), len(commonBytes)+4+len(bz)) copy(resultBytes, commonBytes) - resultBytes = append(resultBytes, appended.Bytes()...) + resultBytes = append(resultBytes, lenBuf[:]...) + resultBytes = append(resultBytes, bz...) return resultBytes } diff --git a/tss-lib/common/int_test.go b/tss-lib/common/int_test.go new file mode 100644 index 0000000..d6fb265 --- /dev/null +++ b/tss-lib/common/int_test.go @@ -0,0 +1,370 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package common + +import ( + "math/big" + "testing" +) + +// --------------------------------------------------------------------------- +// modInt.Add +// --------------------------------------------------------------------------- + +func TestModIntAddBasic(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 3 + 5 = 8 mod 7 = 1 + result := mod.Add(big.NewInt(3), big.NewInt(5)) + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("Add(3, 5) mod 7 = %s, want 1", result) + } +} + +func TestModIntAddNoWrap(t *testing.T) { + mod := ModInt(big.NewInt(10)) + // 3 + 4 = 7 mod 10 = 7 + result := mod.Add(big.NewInt(3), big.NewInt(4)) + if result.Cmp(big.NewInt(7)) != 0 { + t.Fatalf("Add(3, 4) mod 10 = %s, want 7", result) + } +} + +func TestModIntAddWithZero(t *testing.T) { + mod := ModInt(big.NewInt(7)) + result := mod.Add(big.NewInt(5), big.NewInt(0)) + if result.Cmp(big.NewInt(5)) != 0 { + t.Fatalf("Add(5, 0) mod 7 = %s, want 5", result) + } +} + +func TestModIntAddNegativeInputs(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // -3 + 5 = 2 mod 7 = 2 + result := mod.Add(big.NewInt(-3), big.NewInt(5)) + if result.Cmp(big.NewInt(2)) != 0 { + t.Fatalf("Add(-3, 5) mod 7 = %s, want 2", result) + } +} + +// --------------------------------------------------------------------------- +// modInt.Sub +// --------------------------------------------------------------------------- + +func TestModIntSubBasic(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 5 - 3 = 2 mod 7 = 2 + result := mod.Sub(big.NewInt(5), big.NewInt(3)) + if result.Cmp(big.NewInt(2)) != 0 { + t.Fatalf("Sub(5, 3) mod 7 = %s, want 2", result) + } +} + +func TestModIntSubNegativeResult(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 3 - 5 = -2 mod 7 = 5 (Go's Mod returns non-negative for positive modulus) + result := mod.Sub(big.NewInt(3), big.NewInt(5)) + if result.Cmp(big.NewInt(5)) != 0 { + t.Fatalf("Sub(3, 5) mod 7 = %s, want 5", result) + } +} + +func TestModIntSubSelf(t *testing.T) { + mod := ModInt(big.NewInt(7)) + result := mod.Sub(big.NewInt(4), big.NewInt(4)) + if result.Cmp(big.NewInt(0)) != 0 { + t.Fatalf("Sub(4, 4) mod 7 = %s, want 0", result) + } +} + +// --------------------------------------------------------------------------- +// modInt.Mul +// --------------------------------------------------------------------------- + +func TestModIntMulBasic(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 3 * 5 = 15 mod 7 = 1 + result := mod.Mul(big.NewInt(3), big.NewInt(5)) + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("Mul(3, 5) mod 7 = %s, want 1", result) + } +} + +func TestModIntMulByZero(t *testing.T) { + mod := ModInt(big.NewInt(7)) + result := mod.Mul(big.NewInt(5), big.NewInt(0)) + if result.Cmp(big.NewInt(0)) != 0 { + t.Fatalf("Mul(5, 0) mod 7 = %s, want 0", result) + } +} + +func TestModIntMulByOne(t *testing.T) { + mod := ModInt(big.NewInt(7)) + result := mod.Mul(big.NewInt(5), big.NewInt(1)) + if result.Cmp(big.NewInt(5)) != 0 { + t.Fatalf("Mul(5, 1) mod 7 = %s, want 5", result) + } +} + +func TestModIntMulLargeValues(t *testing.T) { + mod := ModInt(big.NewInt(100)) + // 50 * 50 = 2500 mod 100 = 0 + result := mod.Mul(big.NewInt(50), big.NewInt(50)) + if result.Cmp(big.NewInt(0)) != 0 { + t.Fatalf("Mul(50, 50) mod 100 = %s, want 0", result) + } +} + +// --------------------------------------------------------------------------- +// modInt.Exp +// --------------------------------------------------------------------------- + +func TestModIntExpBasic(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 2^3 = 8 mod 7 = 1 + result := mod.Exp(big.NewInt(2), big.NewInt(3)) + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("Exp(2, 3) mod 7 = %s, want 1", result) + } +} + +func TestModIntExpZeroExponent(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // x^0 = 1 mod 7 = 1 + result := mod.Exp(big.NewInt(5), big.NewInt(0)) + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("Exp(5, 0) mod 7 = %s, want 1", result) + } +} + +func TestModIntExpZeroBase(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 0^5 = 0 mod 7 = 0 + result := mod.Exp(big.NewInt(0), big.NewInt(5)) + if result.Cmp(big.NewInt(0)) != 0 { + t.Fatalf("Exp(0, 5) mod 7 = %s, want 0", result) + } +} + +func TestModIntExpLargeValues(t *testing.T) { + mod := ModInt(big.NewInt(13)) + // 2^10 = 1024 mod 13 = 11 (1024 = 78*13 + 10... let me compute: 78*13=1014, 1024-1014=10) + result := mod.Exp(big.NewInt(2), big.NewInt(10)) + expected := new(big.Int).Exp(big.NewInt(2), big.NewInt(10), big.NewInt(13)) + if result.Cmp(expected) != 0 { + t.Fatalf("Exp(2, 10) mod 13 = %s, want %s", result, expected) + } +} + +// TestModIntExpNegativeExponentCoprime documents that since Go 1.12 +// (https://github.com/golang/go/issues/25865), big.Int.Exp with a negative +// exponent and non-nil modulus computes the modular inverse raised to |exp|. +// Before Go 1.12, this silently returned 1 (wrong answer, no error). +// This behavior is relied upon by crypto/mta/range_proof.go (minusE pattern). +func TestModIntExpNegativeExponentCoprime(t *testing.T) { + mod := ModInt(big.NewInt(7)) + result := mod.Exp(big.NewInt(2), big.NewInt(-3)) + // 2^{-3} mod 7 = (2^{-1})^3 mod 7 = 4^3 mod 7 = 64 mod 7 = 1 + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("Exp(2, -3) mod 7 = %s, want 1", result) + } + + // Verify against manual modular inverse computation. + inv := mod.ModInverse(big.NewInt(2)) + manual := mod.Exp(inv, big.NewInt(3)) + if result.Cmp(manual) != 0 { + t.Fatalf("Exp(2, -3) mod 7 = %s, manual (2^-1)^3 = %s — mismatch", result, manual) + } +} + +// TestModIntExpNegativeExponentNonCoprime documents that when the base and +// modulus are NOT coprime, big.Int.Exp returns nil. Since modInt.Exp uses +// `return new(big.Int).Exp(x, y, mi.i())`, it returns the nil from Exp +// directly. Any caller that uses the result without a nil check will PANIC. +// +// This is why the FAC proof Verify() explicitly handles negative V with +// ModInverse + nil check rather than relying on modInt.Exp with a negative +// exponent. The MTA range proof's use of minusE is safe only because +// Paillier ciphertexts are always coprime to NSquare. +func TestModIntExpNegativeExponentNonCoprime(t *testing.T) { + mod := ModInt(big.NewInt(6)) + // 2 and 6 are not coprime (gcd=2), so 2^{-1} mod 6 does not exist. + // big.Int.Exp returns nil, and modInt.Exp propagates that nil. + result := mod.Exp(big.NewInt(2), big.NewInt(-3)) + + // modInt.Exp returns nil — any subsequent use will panic. + if result != nil { + t.Fatalf("modInt.Exp should return nil for non-coprime base/modulus, got %s", result) + } + + // Contrast: ModInverse also correctly returns nil for non-invertible input. + inv := mod.ModInverse(big.NewInt(2)) + if inv != nil { + t.Fatalf("ModInverse(2) mod 6 should be nil, got %s", inv) + } + + // Demonstrate the panic: using nil result would crash. + defer func() { + if r := recover(); r == nil { + t.Fatal("using nil result of Exp should panic") + } + }() + _ = mod.Mul(mod.Exp(big.NewInt(2), big.NewInt(-3)), big.NewInt(1)) +} + +// TestBigIntExpNilReturnContract directly tests big.Int.Exp's nil return +// contract to detect if a future Go version changes this behavior. +// If this test fails, all code using modInt.Exp with negative exponents +// must be audited. +func TestBigIntExpNilReturnContract(t *testing.T) { + z := new(big.Int) + ret := z.Exp(big.NewInt(2), big.NewInt(-3), big.NewInt(6)) + + // big.Int.Exp returns nil when base and modulus are not coprime. + if ret != nil { + t.Fatal("big.Int.Exp should return nil for non-coprime base/modulus with negative exponent") + } + + // z (the receiver) should remain unchanged at its initial value (0). + if z.Sign() != 0 { + t.Fatalf("receiver z should remain 0, got %s", z) + } + + // Positive case: coprime base/modulus returns non-nil. + z2 := new(big.Int) + ret2 := z2.Exp(big.NewInt(5), big.NewInt(-3), big.NewInt(7)) + if ret2 == nil { + t.Fatal("big.Int.Exp should return non-nil for coprime base/modulus") + } + if ret2 != z2 { + t.Fatal("big.Int.Exp should return the receiver on success") + } +} + +// --------------------------------------------------------------------------- +// modInt.ModInverse +// --------------------------------------------------------------------------- + +func TestModIntModInverseBasic(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 3^{-1} mod 7 = 5 (since 3*5=15=2*7+1) + result := mod.ModInverse(big.NewInt(3)) + if result == nil { + t.Fatal("ModInverse(3) mod 7 should not be nil") + } + if result.Cmp(big.NewInt(5)) != 0 { + t.Fatalf("ModInverse(3) mod 7 = %s, want 5", result) + } +} + +func TestModIntModInverseOne(t *testing.T) { + mod := ModInt(big.NewInt(7)) + // 1^{-1} mod 7 = 1 + result := mod.ModInverse(big.NewInt(1)) + if result.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("ModInverse(1) mod 7 = %s, want 1", result) + } +} + +func TestModIntModInverseNonInvertible(t *testing.T) { + mod := ModInt(big.NewInt(6)) + // 2 is not invertible mod 6 (gcd(2,6)=2!=1) + result := mod.ModInverse(big.NewInt(2)) + if result != nil { + t.Fatalf("ModInverse(2) mod 6 should be nil (non-invertible), got %s", result) + } +} + +func TestModIntModInverseVerify(t *testing.T) { + mod := ModInt(big.NewInt(13)) + g := big.NewInt(5) + inv := mod.ModInverse(g) + if inv == nil { + t.Fatal("ModInverse(5) mod 13 should not be nil") + } + // g * inv mod 13 should equal 1. + product := mod.Mul(g, inv) + if product.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("5 * ModInverse(5) mod 13 = %s, want 1", product) + } +} + +// --------------------------------------------------------------------------- +// modInt does not mutate inputs +// --------------------------------------------------------------------------- + +func TestModIntDoesNotMutateInputs(t *testing.T) { + mod := ModInt(big.NewInt(7)) + x := big.NewInt(10) + y := big.NewInt(3) + xCopy := new(big.Int).Set(x) + yCopy := new(big.Int).Set(y) + + mod.Add(x, y) + if x.Cmp(xCopy) != 0 { + t.Fatalf("Add mutated x: was %s, now %s", xCopy, x) + } + if y.Cmp(yCopy) != 0 { + t.Fatalf("Add mutated y: was %s, now %s", yCopy, y) + } + + mod.Sub(x, y) + if x.Cmp(xCopy) != 0 { + t.Fatalf("Sub mutated x: was %s, now %s", xCopy, x) + } + + mod.Mul(x, y) + if x.Cmp(xCopy) != 0 { + t.Fatalf("Mul mutated x: was %s, now %s", xCopy, x) + } +} + +// --------------------------------------------------------------------------- +// IsInInterval +// --------------------------------------------------------------------------- + +func TestIsInIntervalInRange(t *testing.T) { + // 5 is in [0, 10) + if !IsInInterval(big.NewInt(5), big.NewInt(10)) { + t.Fatal("5 should be in [0, 10)") + } +} + +func TestIsInIntervalZero(t *testing.T) { + // 0 is in [0, 10) — lower bound is inclusive + if !IsInInterval(big.NewInt(0), big.NewInt(10)) { + t.Fatal("0 should be in [0, 10)") + } +} + +func TestIsInIntervalAtBound(t *testing.T) { + // 10 is NOT in [0, 10) — upper bound is exclusive + if IsInInterval(big.NewInt(10), big.NewInt(10)) { + t.Fatal("10 should not be in [0, 10)") + } +} + +func TestIsInIntervalNegative(t *testing.T) { + // -1 is NOT in [0, 10) + if IsInInterval(big.NewInt(-1), big.NewInt(10)) { + t.Fatal("-1 should not be in [0, 10)") + } +} + +func TestIsInIntervalAboveBound(t *testing.T) { + // 15 is NOT in [0, 10) + if IsInInterval(big.NewInt(15), big.NewInt(10)) { + t.Fatal("15 should not be in [0, 10)") + } +} + +func TestIsInIntervalBoundOne(t *testing.T) { + // Only 0 is in [0, 1) + if !IsInInterval(big.NewInt(0), big.NewInt(1)) { + t.Fatal("0 should be in [0, 1)") + } + if IsInInterval(big.NewInt(1), big.NewInt(1)) { + t.Fatal("1 should not be in [0, 1)") + } +} diff --git a/tss-lib/common/negative_test.go b/tss-lib/common/negative_test.go new file mode 100644 index 0000000..e1e1e21 --- /dev/null +++ b/tss-lib/common/negative_test.go @@ -0,0 +1,115 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package common + +import ( + "math/big" + "testing" +) + +// --- SHA512_256 error paths --- + +func TestSHA512_256Empty(t *testing.T) { + result := SHA512_256() + if result != nil { + t.Fatal("empty input should return nil") + } +} + +func TestSHA512_256iOneNilNeg(t *testing.T) { + result := SHA512_256iOne(nil) + if result != nil { + t.Fatal("nil input should return nil") + } +} + +func TestSHA512_256iOneValid(t *testing.T) { + result := SHA512_256iOne(big.NewInt(42)) + if result == nil || result.Sign() == 0 { + t.Fatal("valid input should return non-nil, non-zero") + } +} + +// --- MustGetRandomInt panic paths --- + +func TestMustGetRandomIntZeroBits(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("expected panic for zero bits") + } + }() + MustGetRandomInt(nil, 0) +} + +func TestMustGetRandomIntNegativeBits(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("expected panic for negative bits") + } + }() + MustGetRandomInt(nil, -1) +} + +// --- GetRandomPrimeInt edge cases --- + +func TestGetRandomPrimeIntZeroBits(t *testing.T) { + result := GetRandomPrimeInt(nil, 0) + if result != nil { + t.Fatal("zero bits should return nil") + } +} + +func TestGetRandomPrimeIntNegativeBits(t *testing.T) { + result := GetRandomPrimeInt(nil, -1) + if result != nil { + t.Fatal("negative bits should return nil") + } +} + +// --- GetRandomPositiveRelativelyPrimeInt edge cases --- + +func TestGetRandomRelPrimeNilN(t *testing.T) { + result := GetRandomPositiveRelativelyPrimeInt(nil, nil) + if result != nil { + t.Fatal("nil n should return nil") + } +} + +func TestGetRandomRelPrimeZeroN(t *testing.T) { + result := GetRandomPositiveRelativelyPrimeInt(nil, big.NewInt(0)) + if result != nil { + t.Fatal("zero n should return nil") + } +} + +// --- IsNumberInMultiplicativeGroup edge cases --- + +func TestIsNumberInMultiplicativeGroupNilArgs(t *testing.T) { + if IsNumberInMultiplicativeGroup(nil, big.NewInt(1)) { + t.Fatal("nil n should return false") + } + if IsNumberInMultiplicativeGroup(big.NewInt(10), nil) { + t.Fatal("nil v should return false") + } + if IsNumberInMultiplicativeGroup(big.NewInt(0), big.NewInt(1)) { + t.Fatal("zero n should return false") + } +} + +// --- GetRandomBytes edge cases --- + +func TestGetRandomBytesZeroLength(t *testing.T) { + _, err := GetRandomBytes(nil, 0) + if err == nil { + t.Fatal("expected error for zero length") + } +} + +func TestGetRandomBytesNegativeLength(t *testing.T) { + _, err := GetRandomBytes(nil, -1) + if err == nil { + t.Fatal("expected error for negative length") + } +} diff --git a/tss-lib/common/random.go b/tss-lib/common/random.go index 040492b..f679fe7 100644 --- a/tss-lib/common/random.go +++ b/tss-lib/common/random.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package common @@ -25,25 +24,31 @@ func MustGetRandomInt(rand io.Reader, bits int) *big.Int { panic(fmt.Errorf("MustGetRandomInt: bits should be positive, non-zero and less than %d", mustGetRandomIntMaxBits)) } // Max random value e.g. 2^256 - 1 - max := new(big.Int) - max = max.Exp(two, big.NewInt(int64(bits)), nil).Sub(max, one) + maxVal := new(big.Int) + maxVal = maxVal.Exp(two, big.NewInt(int64(bits)), nil).Sub(maxVal, one) // Generate cryptographically strong pseudo-random int between 0 - max - n, err := cryptorand.Int(rand, max) + n, err := cryptorand.Int(rand, maxVal) if err != nil { panic(errors.Wrap(err, "rand.Int failure in MustGetRandomInt!")) } return n } +// [FORK] Two fixes vs upstream: +// 1. Guard: upstream checks `zero.Cmp(lessThan) != -1` which allows lessThan=1 +// through, then returns 0 (not positive). We require lessThan >= 2 so the +// interval [1, lessThan) is non-empty. +// 2. Loop condition: upstream only checks `try.Cmp(lessThan) < 0` and can +// return zero (which is not positive). We add `try.Sign() > 0`. func GetRandomPositiveInt(rand io.Reader, lessThan *big.Int) *big.Int { - if lessThan == nil || zero.Cmp(lessThan) != -1 { + if lessThan == nil || lessThan.Cmp(two) < 0 { return nil } var try *big.Int for { try = MustGetRandomInt(rand, lessThan.BitLen()) - if try.Cmp(lessThan) < 0 { + if try.Sign() > 0 && try.Cmp(lessThan) < 0 { break } } diff --git a/tss-lib/common/random_test.go b/tss-lib/common/random_test.go index fa6a8b1..cfccb2a 100644 --- a/tss-lib/common/random_test.go +++ b/tss-lib/common/random_test.go @@ -11,9 +11,7 @@ import ( "math/big" "testing" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) const ( @@ -22,27 +20,43 @@ const ( func TestGetRandomInt(t *testing.T) { rnd := common.MustGetRandomInt(rand.Reader, randomIntBitLen) - assert.NotZero(t, rnd, "rand int should not be zero") + if rnd == nil { + t.Fatal("rand int should not be zero") + } } func TestGetRandomPositiveInt(t *testing.T) { rnd := common.MustGetRandomInt(rand.Reader, randomIntBitLen) rndPos := common.GetRandomPositiveInt(rand.Reader, rnd) - assert.NotZero(t, rndPos, "rand int should not be zero") - assert.True(t, rndPos.Cmp(big.NewInt(0)) == 1, "rand int should be positive") + if rndPos == nil { + t.Fatal("rand int should not be zero") + } + if rndPos.Cmp(big.NewInt(0)) != 1 { + t.Fatal("rand int should be positive") + } } func TestGetRandomPositiveRelativelyPrimeInt(t *testing.T) { rnd := common.MustGetRandomInt(rand.Reader, randomIntBitLen) rndPosRP := common.GetRandomPositiveRelativelyPrimeInt(rand.Reader, rnd) - assert.NotZero(t, rndPosRP, "rand int should not be zero") - assert.True(t, common.IsNumberInMultiplicativeGroup(rnd, rndPosRP)) - assert.True(t, rndPosRP.Cmp(big.NewInt(0)) == 1, "rand int should be positive") + if rndPosRP == nil { + t.Fatal("rand int should not be zero") + } + if !common.IsNumberInMultiplicativeGroup(rnd, rndPosRP) { + t.Fatal("expected true") + } + if rndPosRP.Cmp(big.NewInt(0)) != 1 { + t.Fatal("rand int should be positive") + } // TODO test for relative primeness } func TestGetRandomPrimeInt(t *testing.T) { prime := common.GetRandomPrimeInt(rand.Reader, randomIntBitLen) - assert.NotZero(t, prime, "rand prime should not be zero") - assert.True(t, prime.ProbablyPrime(50), "rand prime should be prime") + if prime == nil { + t.Fatal("rand prime should not be zero") + } + if !prime.ProbablyPrime(50) { + t.Fatal("rand prime should be prime") + } } diff --git a/tss-lib/common/safe_prime.go b/tss-lib/common/safe_prime.go index 6d14e04..dd87c4e 100644 --- a/tss-lib/common/safe_prime.go +++ b/tss-lib/common/safe_prime.go @@ -152,7 +152,7 @@ func GetRandomSafePrimesConcurrent(ctx context.Context, bitLen, numPrimes int, c ) } - needed := int32(numPrimes) + needed := int32(numPrimes) //nolint:gosec // numPrimes is a small count, fits in int32 for { select { case result := <-primeCh: @@ -203,16 +203,9 @@ func GetRandomSafePrimesConcurrent(ctx context.Context, bitLen, numPrimes int, c // Miller-Rabin and Baillie-PSW for `p`. // If `q` and `p` are found to be prime, return them as a result. If not, go // back to the point 1. -func runGenPrimeRoutine( - ctx context.Context, - primeCh chan<- *GermainSafePrime, - errCh chan<- error, - waitGroup *sync.WaitGroup, - rand io.Reader, - pBitLen int, -) { +func runGenPrimeRoutine(ctx context.Context, primeCh chan<- *GermainSafePrime, errCh chan<- error, waitGroup *sync.WaitGroup, rand io.Reader, pBitLen int) { qBitLen := pBitLen - 1 - b := uint(qBitLen % 8) + b := uint(qBitLen % 8) //nolint:gosec // result is 0-7 if b == 0 { b = 8 } @@ -239,7 +232,7 @@ func runGenPrimeRoutine( // Clear bits in the first byte to make sure the candidate has // a size <= bits. - bytes[0] &= uint8(int(1<= length { + return src } - return src + padded := make([]byte, length) + copy(padded[length-len(src):], src) + return padded } diff --git a/tss-lib/crypto/ckd/child_key_derivation.go b/tss-lib/crypto/ckd/child_key_derivation.go index 3187029..712f230 100644 --- a/tss-lib/crypto/ckd/child_key_derivation.go +++ b/tss-lib/crypto/ckd/child_key_derivation.go @@ -1,4 +1,7 @@ -// Copyright © Swingby +// Copyright (c) Swingby +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package ckd @@ -14,11 +17,12 @@ import ( "hash" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcutil/base58" - "golang.org/x/crypto/ripemd160" + "golang.org/x/crypto/ripemd160" //nolint:staticcheck,gosec // BIP-32 requires RIPEMD-160 + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" ) type ExtendedKey struct { @@ -70,7 +74,7 @@ func (k *ExtendedKey) String() string { serializedBytes = append(serializedBytes, k.ParentFP...) serializedBytes = append(serializedBytes, childNumBytes[:]...) serializedBytes = append(serializedBytes, k.ChainCode...) - pubKeyBytes := serializeCompressed(k.PublicKey.X, k.PublicKey.Y) + pubKeyBytes := serializeCompressed(k.X, k.Y) serializedBytes = append(serializedBytes, pubKeyBytes...) checkSum := doubleHashB(serializedBytes)[:4] @@ -117,6 +121,9 @@ func NewExtendedKeyFromString(key string, curve elliptic.Curve) (*ExtendedKey, e } } else { px, py := elliptic.Unmarshal(curve, keyData) + if px == nil { + return nil, errors.New("failed to unmarshal public key from extended key data") + } pubKey = ecdsa.PublicKey{ Curve: curve, X: px, @@ -146,7 +153,7 @@ func calcHash(buf []byte, hasher hash.Hash) []byte { } func hash160(buf []byte) []byte { - return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) + return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) //nolint:gosec // BIP-32 requires RIPEMD-160 } func isOdd(a *big.Int) bool { @@ -181,7 +188,7 @@ func serializeCompressed(publicKeyX *big.Int, publicKeyY *big.Int) []byte { } func DeriveChildKeyFromHierarchy(indicesHierarchy []uint32, pk *ExtendedKey, mod *big.Int, curve elliptic.Curve) (*big.Int, *ExtendedKey, error) { - var k = pk + k := pk var err error var childKey *ExtendedKey mod_ := common.ModInt(mod) @@ -235,12 +242,16 @@ func DeriveChildKey(index uint32, pk *ExtendedKey, curve elliptic.Curve) (*big.I return nil, nil, err } + // Note: the fork's ScalarBaseMult (crypto/ecpoint.go) returns identity (0,0) instead + // of panicking. The identity check below is unchanged from upstream. deltaG := crypto.ScalarBaseMult(curve, ilNum) if deltaG.X().Sign() == 0 || deltaG.Y().Sign() == 0 { err = errors.New("invalid child") common.Logger.Error("error invalid child") return nil, nil, err } + // Note: the fork's ECPoint.Add (crypto/ecpoint.go) adds nil/curve-mismatch guards. + // This callsite and its error handling are unchanged from upstream. childCryptoPk, err := cryptoPk.Add(deltaG) if err != nil { common.Logger.Error("error adding delta G to parent key") diff --git a/tss-lib/crypto/ckd/child_key_derivation_test.go b/tss-lib/crypto/ckd/child_key_derivation_test.go index 321ad2d..add6a7c 100644 --- a/tss-lib/crypto/ckd/child_key_derivation_test.go +++ b/tss-lib/crypto/ckd/child_key_derivation_test.go @@ -9,8 +9,9 @@ package ckd_test import ( "testing" - . "github.com/hemilabs/x/tss-lib/v2/crypto/ckd" "github.com/btcsuite/btcd/btcec/v2" + + . "github.com/hemilabs/x/tss-lib/v3/crypto/ckd" ) func TestPublicDerivation(t *testing.T) { diff --git a/tss-lib/crypto/ckd/coverage_test.go b/tss-lib/crypto/ckd/coverage_test.go new file mode 100644 index 0000000..c51d611 --- /dev/null +++ b/tss-lib/crypto/ckd/coverage_test.go @@ -0,0 +1,95 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package ckd_test + +import ( + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + + . "github.com/hemilabs/x/tss-lib/v3/crypto/ckd" +) + +func TestDeriveChildKeyFromHierarchy(t *testing.T) { + masterPubKey := "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + wantPub := "xpub6BqyndF6rhZqmgktFCBcapkwubGxPqoAZtQaYewJHXVKZcLdnqBVC8N6f6FSHWUghjuTLeubWyQWfJdk2G3tGgvgj3qngo4vLTnnSjAZckv" + + ec := btcec.S256() + extKey, err := NewExtendedKeyFromString(masterPubKey, ec) + if err != nil { + t.Fatalf("NewExtendedKeyFromString: %v", err) + } + + path := []uint32{0, 1, 2} + _, childKey, err := DeriveChildKeyFromHierarchy(path, extKey, ec.Params().N, ec) + if err != nil { + t.Fatalf("DeriveChildKeyFromHierarchy: %v", err) + } + if childKey.String() != wantPub { + t.Fatalf("mismatch:\n got: %s\n want: %s", childKey.String(), wantPub) + } +} + +func TestDeriveChildKeyFromHierarchyEmpty(t *testing.T) { + masterPubKey := "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + + ec := btcec.S256() + extKey, err := NewExtendedKeyFromString(masterPubKey, ec) + if err != nil { + t.Fatalf("NewExtendedKeyFromString: %v", err) + } + + // Empty path should return the master key unchanged. + delta, childKey, err := DeriveChildKeyFromHierarchy([]uint32{}, extKey, ec.Params().N, ec) + if err != nil { + t.Fatalf("DeriveChildKeyFromHierarchy(empty): %v", err) + } + if delta.Sign() != 0 { + t.Fatalf("expected zero delta for empty path, got %v", delta) + } + if childKey.String() != masterPubKey { + t.Fatal("empty path should return master key") + } +} + +func TestNewExtendedKeyFromStringBadLength(t *testing.T) { + _, err := NewExtendedKeyFromString("abc", btcec.S256()) + if err == nil { + t.Fatal("short base58 should fail") + } +} + +func TestNewExtendedKeyFromStringBadChecksum(t *testing.T) { + // Valid-length but corrupt checksum. + masterPubKey := "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + ec := btcec.S256() + // Verify the valid key works first. + _, err := NewExtendedKeyFromString(masterPubKey, ec) + if err != nil { + t.Fatalf("valid key should work: %v", err) + } + // Flip a character to corrupt it. + bad := []byte(masterPubKey) + bad[len(bad)-2] ^= 0x01 + _, err = NewExtendedKeyFromString(string(bad), ec) + if err == nil { + t.Fatal("bad checksum should fail") + } +} + +func TestPaddedBytesShortSrc(t *testing.T) { + // Exercise the padding path where src is shorter than size. + masterPubKey := "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + ec := btcec.S256() + extKey, err := NewExtendedKeyFromString(masterPubKey, ec) + if err != nil { + t.Fatalf("NewExtendedKeyFromString: %v", err) + } + // DeriveChildKey exercises paddedBytes internally. + _, _, err = DeriveChildKey(0, extKey, ec) + if err != nil { + t.Fatalf("DeriveChildKey: %v", err) + } +} diff --git a/tss-lib/crypto/commitments/binding_test.go b/tss-lib/crypto/commitments/binding_test.go new file mode 100644 index 0000000..d968675 --- /dev/null +++ b/tss-lib/crypto/commitments/binding_test.go @@ -0,0 +1,70 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package commitments + +import ( + "crypto/rand" + "math/big" + "testing" +) + +// TestCommitmentBinding verifies that a commitment to secret A cannot +// be opened as secret B. This is the binding property — it fails if +// the underlying hash function is replaced with a constant (e.g. the +// "lolz no" stub), because then Hash(r||A) == Hash(r||B) for all +// inputs, making the commitment trivially forgeable. +func TestCommitmentBinding(t *testing.T) { + secretA := big.NewInt(42) + secretB := big.NewInt(99) + + // Commit to secretA. + cmt := NewHashCommitment(rand.Reader, secretA) + + // Verify that the commitment opens correctly. + ok, _ := cmt.DeCommit() + if !ok { + t.Fatal("commitment to A should open correctly") + } + + // Now tamper: replace the decommitment's secret with B. + // D[0] is the randomness, D[1] is the secret. + if len(cmt.D) < 2 { + t.Fatal("decommitment too short") + } + cmt.D[len(cmt.D)-1] = secretB + + // Must fail — the commitment was to A, not B. + ok, _ = cmt.DeCommit() + if ok { + t.Fatal("commitment binding broken: opened commitment to A as B") + } +} + +// TestCommitmentHiding verifies that two commitments to different +// secrets produce different commitment values. A constant hash +// would make them identical. +func TestCommitmentHiding(t *testing.T) { + cmtA := NewHashCommitment(rand.Reader, big.NewInt(1)) + cmtB := NewHashCommitment(rand.Reader, big.NewInt(2)) + + if cmtA.C.Cmp(cmtB.C) == 0 { + t.Fatal("commitments to different secrets should differ") + } +} + +// TestDLNProofSoundness is in crypto/dlnproof — but we add a quick +// sanity here: the commitment scheme's Verify recomputes the hash +// and compares. With a constant hash, Verify(wrong_D) would pass. +func TestCommitmentVerifyRejectsWrongRandomness(t *testing.T) { + cmt := NewHashCommitment(rand.Reader, big.NewInt(7)) + + // Tamper with the randomness. + cmt.D[0] = new(big.Int).Add(cmt.D[0], big.NewInt(1)) + + ok, _ := cmt.DeCommit() + if ok { + t.Fatal("verify should reject tampered randomness") + } +} diff --git a/tss-lib/crypto/commitments/commitment.go b/tss-lib/crypto/commitments/commitment.go index 57faa14..e0eca9d 100644 --- a/tss-lib/crypto/commitments/commitment.go +++ b/tss-lib/crypto/commitments/commitment.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. // partly ported from: // https://github.com/KZen-networks/curv/blob/78a70f43f5eda376e5888ce33aec18962f572bbe/src/cryptographic_primitives/commitments/hash_commitment.rs @@ -13,7 +12,7 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) const ( @@ -55,7 +54,10 @@ func NewHashDeCommitmentFromBytes(marshalled [][]byte) HashDeCommitment { func (cmt *HashCommitDecommit) Verify() bool { C, D := cmt.C, cmt.D - if C == nil || D == nil { + // [FORK] Upstream only checks `C == nil || D == nil`. Added len(D) < 2 check: + // D must contain at least the randomness element plus one secret. Without this, + // a decommitment with only the randomness (no secret) could pass verification. + if C == nil || D == nil || len(D) < 2 { return false } hash := common.SHA512_256i(D...) diff --git a/tss-lib/crypto/commitments/commitment_builder.go b/tss-lib/crypto/commitments/commitment_builder.go index 384b1da..cb0ffb1 100644 --- a/tss-lib/crypto/commitments/commitment_builder.go +++ b/tss-lib/crypto/commitments/commitment_builder.go @@ -1,8 +1,7 @@ -// Copyright © 2019-2020 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019-2020 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package commitments @@ -57,7 +56,7 @@ func (b *builder) Secrets() ([]*big.Int, error) { } func ParseSecrets(secrets []*big.Int) ([][]*big.Int, error) { - if secrets == nil || len(secrets) < 2 { + if len(secrets) < 2 { return nil, errors.New("ParseSecrets: secrets == nil or is too small") } var el, nextPartLen int64 @@ -69,9 +68,9 @@ func ParseSecrets(secrets []*big.Int) ([][]*big.Int, error) { return nil, errors.New("ParseSecrets: `el` overflow") } if isLenEl { - nextPartLen = secrets[el].Int64() - if MaxPartSize < nextPartLen { - return nil, fmt.Errorf("ParseSecrets: commitment part too large: part %d, size %d", len(parts), nextPartLen) + nextPartLen = secrets[el].Int64() //nolint:gosec // el < inLen checked by loop + if nextPartLen < 0 || MaxPartSize < nextPartLen { + return nil, fmt.Errorf("ParseSecrets: invalid commitment part size: part %d, size %d", len(parts), nextPartLen) } el += 1 } else { diff --git a/tss-lib/crypto/commitments/commitment_fork_test.go b/tss-lib/crypto/commitments/commitment_fork_test.go new file mode 100644 index 0000000..79862e3 --- /dev/null +++ b/tss-lib/crypto/commitments/commitment_fork_test.go @@ -0,0 +1,44 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package commitments + +import ( + "crypto/rand" + "math/big" + "testing" +) + +func TestVerifyRejectsEmptyD(t *testing.T) { + cmt := NewHashCommitment(rand.Reader, big.NewInt(42)) + cmt.D = []*big.Int{} + if cmt.Verify() { + t.Fatal("empty D should be rejected") + } +} + +func TestVerifyRejectsSingletonD(t *testing.T) { + cmt := NewHashCommitment(rand.Reader, big.NewInt(42)) + cmt.D = []*big.Int{big.NewInt(42)} + if cmt.Verify() { + t.Fatal("singleton D (missing randomness or secret) should be rejected") + } +} + +func TestVerifyRejectsNilD(t *testing.T) { + cmt := NewHashCommitment(rand.Reader, big.NewInt(42)) + cmt.D = nil + if cmt.Verify() { + t.Fatal("nil D should be rejected") + } +} + +func TestDeCommitRejectsSingletonD(t *testing.T) { + cmt := NewHashCommitment(rand.Reader, big.NewInt(42)) + cmt.D = []*big.Int{big.NewInt(42)} + ok, _ := cmt.DeCommit() + if ok { + t.Fatal("DeCommit should fail when D has only one element") + } +} diff --git a/tss-lib/crypto/commitments/commitment_test.go b/tss-lib/crypto/commitments/commitment_test.go index 363714f..590381d 100644 --- a/tss-lib/crypto/commitments/commitment_test.go +++ b/tss-lib/crypto/commitments/commitment_test.go @@ -11,9 +11,7 @@ import ( "math/big" "testing" - "github.com/stretchr/testify/assert" - - . "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" + . "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" ) func TestCreateVerify(t *testing.T) { @@ -23,7 +21,9 @@ func TestCreateVerify(t *testing.T) { commitment := NewHashCommitment(rand.Reader, zero, one) pass := commitment.Verify() - assert.True(t, pass, "must pass") + if !pass { + t.Fatal("must pass") + } } func TestDeCommit(t *testing.T) { @@ -33,7 +33,11 @@ func TestDeCommit(t *testing.T) { commitment := NewHashCommitment(rand.Reader, zero, one) pass, secrets := commitment.DeCommit() - assert.True(t, pass, "must pass") + if !pass { + t.Fatal("must pass") + } - assert.NotZero(t, len(secrets), "len(secrets) must be non-zero") + if len(secrets) == 0 { + t.Fatal("len(secrets) must be non-zero") + } } diff --git a/tss-lib/crypto/commitments/coverage_test.go b/tss-lib/crypto/commitments/coverage_test.go new file mode 100644 index 0000000..9d38c29 --- /dev/null +++ b/tss-lib/crypto/commitments/coverage_test.go @@ -0,0 +1,110 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package commitments + +import ( + "math/big" + "testing" +) + +func TestNewHashDeCommitmentFromBytes(t *testing.T) { + d := NewHashDeCommitmentFromBytes([][]byte{ + big.NewInt(1).Bytes(), + big.NewInt(2).Bytes(), + }) + if len(d) != 2 { + t.Fatalf("expected 2 elements, got %d", len(d)) + } + if d[0].Cmp(big.NewInt(1)) != 0 || d[1].Cmp(big.NewInt(2)) != 0 { + t.Fatal("values mismatch") + } +} + +func TestBuilder(t *testing.T) { + b := NewBuilder() + if b == nil { + t.Fatal("NewBuilder returned nil") + } + if len(b.Parts()) != 0 { + t.Fatal("new builder should have 0 parts") + } + b.AddPart([]*big.Int{big.NewInt(1), big.NewInt(2)}) + b.AddPart([]*big.Int{big.NewInt(3)}) + if len(b.Parts()) != 2 { + t.Fatalf("expected 2 parts, got %d", len(b.Parts())) + } + if len(b.Parts()[0]) != 2 { + t.Fatalf("expected part 0 len 2, got %d", len(b.Parts()[0])) + } +} + +func TestSecretsAndParseSecretsRoundTrip(t *testing.T) { + b := NewBuilder() + b.AddPart([]*big.Int{big.NewInt(10), big.NewInt(20)}) + b.AddPart([]*big.Int{big.NewInt(30)}) + + secrets, err := b.Secrets() + if err != nil { + t.Fatalf("Secrets: %v", err) + } + + parts, err := ParseSecrets(secrets) + if err != nil { + t.Fatalf("ParseSecrets: %v", err) + } + if len(parts) != 2 { + t.Fatalf("expected 2 parts, got %d", len(parts)) + } + if parts[0][0].Cmp(big.NewInt(10)) != 0 || parts[0][1].Cmp(big.NewInt(20)) != 0 { + t.Fatal("part 0 mismatch") + } +} + +func TestParseSecretsTooSmall(t *testing.T) { + _, err := ParseSecrets([]*big.Int{big.NewInt(1)}) + if err == nil { + t.Fatal("expected error for too-small input") + } +} + +func TestParseSecretsNil(t *testing.T) { + _, err := ParseSecrets(nil) + if err == nil { + t.Fatal("expected error for nil input") + } +} + +func TestSecretsTooManyParts(t *testing.T) { + b := NewBuilder() + // PartsCap is 3, add 4 parts + for i := 0; i < 4; i++ { + b.AddPart([]*big.Int{big.NewInt(int64(i))}) + } + _, err := b.Secrets() + if err == nil { + t.Fatal("expected error for too many parts") + } +} + +func TestParseSecretsBadPartLen(t *testing.T) { + // Craft: [length=-1, ...] + _, err := ParseSecrets([]*big.Int{big.NewInt(-1), big.NewInt(0)}) + if err == nil { + t.Fatal("expected error for negative part length") + } +} + +func TestParseSecretsTooManyParts(t *testing.T) { + // Craft secrets with 4 parts (PartsCap=3) + secrets := make([]*big.Int, 0) + for i := 0; i < 4; i++ { + secrets = append(secrets, big.NewInt(1)) // length prefix: 1 + secrets = append(secrets, big.NewInt(int64(i))) // value + } + _, err := ParseSecrets(secrets) + if err == nil { + t.Fatal("expected error for too many parts") + } +} diff --git a/tss-lib/crypto/coverage_test.go b/tss-lib/crypto/coverage_test.go new file mode 100644 index 0000000..24a5518 --- /dev/null +++ b/tss-lib/crypto/coverage_test.go @@ -0,0 +1,148 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package crypto + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestECPointAddNilP1(t *testing.T) { + ec := tss.S256() + p := ScalarBaseMult(ec, big.NewInt(7)) + _, err := p.Add(nil) + if err == nil { + t.Fatal("Add(nil) should error") + } +} + +func TestECPointAddCurveMismatch(t *testing.T) { + p1 := ScalarBaseMult(tss.S256(), big.NewInt(7)) + p2 := ScalarBaseMult(tss.Edwards(), big.NewInt(7)) + _, err := p1.Add(p2) + if err == nil { + t.Fatal("Add with different curves should error") + } +} + +func TestToECDSAPubKey(t *testing.T) { + ec := tss.S256() + p := ScalarBaseMult(ec, big.NewInt(42)) + pk := p.ToECDSAPubKey() + if pk.X.Cmp(p.X()) != 0 || pk.Y.Cmp(p.Y()) != 0 { + t.Fatal("coordinates mismatch") + } + if pk.Curve != ec { + t.Fatal("curve mismatch") + } +} + +func TestSetCurve(t *testing.T) { + p := ScalarBaseMult(tss.S256(), big.NewInt(7)) + if p.Curve() != tss.S256() { + t.Fatal("initial curve wrong") + } + p.SetCurve(tss.Edwards()) + if p.Curve() != tss.Edwards() { + t.Fatal("SetCurve did not update") + } +} + +func TestValidateBasic(t *testing.T) { + ec := tss.S256() + p := ScalarBaseMult(ec, big.NewInt(42)) + if !p.ValidateBasic() { + t.Fatal("valid point should pass") + } + + // nil point + var nilP *ECPoint + if nilP.ValidateBasic() { + t.Fatal("nil should fail") + } +} + +func TestEqualsNilHandling(t *testing.T) { + p := ScalarBaseMult(tss.S256(), big.NewInt(7)) + if p.Equals(nil) { + t.Fatal("Equals(nil) should be false") + } + var nilP *ECPoint + if nilP.Equals(p) { + t.Fatal("nil.Equals(p) should be false") + } +} + +func TestEightInvEight(t *testing.T) { + ec := tss.Edwards() + p := ScalarBaseMult(ec, big.NewInt(42)) + cleared := p.EightInvEight() + if !cleared.Equals(p) { + t.Fatal("EightInvEight should be identity for prime-order subgroup points") + } +} + +func TestIsIdentityEdwardsCoverage(t *testing.T) { + p, err := NewECPoint(tss.Edwards(), big.NewInt(0), big.NewInt(1)) + if err != nil { + t.Fatal(err) + } + if !p.IsIdentity() { + t.Fatal("(0,1) should be identity on Edwards") + } +} + +func TestIsIdentityWeierstrassCoverage(t *testing.T) { + p := NewECPointNoCurveCheck(tss.S256(), big.NewInt(0), big.NewInt(0)) + if !p.IsIdentity() { + t.Fatal("(0,0) should be identity on Weierstrass") + } +} + +func TestECPointJSONRoundTrip(t *testing.T) { + ec := tss.S256() + p := ScalarBaseMult(ec, big.NewInt(42)) + + data, err := json.Marshal(p) + if err != nil { + t.Fatalf("marshal: %v", err) + } + + p2 := new(ECPoint) + if err := json.Unmarshal(data, p2); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if !p.Equals(p2) { + t.Fatal("round-trip mismatch") + } +} + +func TestUnFlattenECPointsOddLength(t *testing.T) { + _, err := UnFlattenECPoints(tss.S256(), []*big.Int{big.NewInt(1)}) + if err == nil { + t.Fatal("odd-length input should error") + } +} + +func TestUnFlattenECPointsNil(t *testing.T) { + _, err := UnFlattenECPoints(tss.S256(), nil) + if err == nil { + t.Fatal("nil input should error") + } +} + +func TestScalarMultIdentity(t *testing.T) { + ec := tss.S256() + N := ec.Params().N + // Multiplying by N should give identity + defer func() { + // ScalarBaseMult(N) may panic on identity — that's fine + _ = recover() + }() + _ = ScalarBaseMult(ec, N) +} diff --git a/tss-lib/crypto/dlnproof/negative_test.go b/tss-lib/crypto/dlnproof/negative_test.go new file mode 100644 index 0000000..5b4d4ba --- /dev/null +++ b/tss-lib/crypto/dlnproof/negative_test.go @@ -0,0 +1,24 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package dlnproof + +import ( + "math/big" + "testing" +) + +func TestUnmarshalDLNProofTooFewParts(t *testing.T) { + _, err := UnmarshalDLNProof([][]byte{big.NewInt(1).Bytes(), big.NewInt(2).Bytes()}) + if err == nil { + t.Fatal("expected error for too few parts") + } +} + +func TestUnmarshalDLNProofEmpty(t *testing.T) { + _, err := UnmarshalDLNProof(nil) + if err == nil { + t.Fatal("expected error for nil input") + } +} diff --git a/tss-lib/crypto/dlnproof/proof.go b/tss-lib/crypto/dlnproof/proof.go index 6ceb441..e3a79c8 100644 --- a/tss-lib/crypto/dlnproof/proof.go +++ b/tss-lib/crypto/dlnproof/proof.go @@ -1,8 +1,7 @@ -// Copyright © 2019-2020 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019-2020 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. // Zero-knowledge proof of knowledge of the discrete logarithm over safe prime product @@ -16,8 +15,8 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - cmts "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/common" + cmts "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" ) const Iterations = 128 @@ -31,7 +30,8 @@ type ( var one = big.NewInt(1) -func NewDLNProof(h1, h2, x, p, q, N *big.Int, rand io.Reader) *Proof { +// [FORK] Session parameter added for SSID domain separation (prevents cross-ceremony replay). +func NewDLNProof(Session []byte, h1, h2, x, p, q, N *big.Int, rand io.Reader) *Proof { pMulQ := new(big.Int).Mul(p, q) modN, modPQ := common.ModInt(N), common.ModInt(pMulQ) a := make([]*big.Int, Iterations) @@ -41,22 +41,27 @@ func NewDLNProof(h1, h2, x, p, q, N *big.Int, rand io.Reader) *Proof { alpha[i] = modN.Exp(h1, a[i]) } msg := append([]*big.Int{h1, h2, N}, alpha[:]...) - c := common.SHA512_256i(msg...) + c := common.SHA512_256i_TAGGED(Session, msg...) t := [Iterations]*big.Int{} cIBI := new(big.Int) for i := range t { cI := c.Bit(i) - cIBI = cIBI.SetInt64(int64(cI)) + cIBI = cIBI.SetUint64(uint64(cI)) t[i] = modPQ.Add(a[i], modPQ.Mul(cIBI, x)) } return &Proof{alpha, t} } -func (p *Proof) Verify(h1, h2, N *big.Int) bool { +func (p *Proof) Verify(Session []byte, h1, h2, N *big.Int) bool { if p == nil { return false } - if N.Sign() != 1 { + if N == nil || N.Sign() != 1 { + return false + } + // [FORK] Reject undersized moduli — DLN proofs are only sound when N is the + // product of two large safe primes (>= 2048-bit modulus). Upstream does not check. + if N.BitLen() < 2048 { return false } modN := common.ModInt(N) @@ -71,27 +76,37 @@ func (p *Proof) Verify(h1, h2, N *big.Int) bool { if h1_.Cmp(h2_) == 0 { return false } + // [FORK] Upstream validates proof elements with range checks in separate loops and nil + // checks inside the verification loop. We consolidate all validation (nil checks, bit-length + // bounds, and range checks) into pre-verification loops to prevent computational DoS via + // oversized exponents before modular reduction. + maxBits := N.BitLen() + 2 for i := range p.T { + if p.T[i] == nil || p.T[i].BitLen() > maxBits { + return false + } a := new(big.Int).Mod(p.T[i], N) if a.Cmp(one) != 1 || a.Cmp(N) != -1 { return false } } for i := range p.Alpha { + if p.Alpha[i] == nil || p.Alpha[i].BitLen() > maxBits { + return false + } a := new(big.Int).Mod(p.Alpha[i], N) if a.Cmp(one) != 1 || a.Cmp(N) != -1 { return false } } + // [FORK] Uses SHA512_256i_TAGGED with Session for SSID domain separation. + // Upstream uses SHA512_256i without any session tag. msg := append([]*big.Int{h1, h2, N}, p.Alpha[:]...) - c := common.SHA512_256i(msg...) + c := common.SHA512_256i_TAGGED(Session, msg...) cIBI := new(big.Int) for i := 0; i < Iterations; i++ { - if p.Alpha[i] == nil || p.T[i] == nil { - return false - } cI := c.Bit(i) - cIBI = cIBI.SetInt64(int64(cI)) + cIBI = cIBI.SetUint64(uint64(cI)) h1ExpTi := modN.Exp(h1, p.T[i]) h2ExpCi := modN.Exp(h2, cIBI) alphaIMulH2ExpCi := modN.Mul(p.Alpha[i], h2ExpCi) diff --git a/tss-lib/crypto/dlnproof/proof_fork_test.go b/tss-lib/crypto/dlnproof/proof_fork_test.go new file mode 100644 index 0000000..1aa90c0 --- /dev/null +++ b/tss-lib/crypto/dlnproof/proof_fork_test.go @@ -0,0 +1,207 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Tests for DLN proof fork changes: SSID session domain separation, +// N.BitLen() < 2048 rejection, and consolidated pre-validation. + +package dlnproof + +import ( + "context" + "crypto/rand" + "math/big" + "runtime" + "testing" + "time" + + "github.com/hemilabs/x/tss-lib/v3/common" +) + +var dlnSession = []byte("dln-fork-test") + +// generateDLNParams generates proper DLN proof parameters at runtime using +// safe primes. Returns h1, h2, x (discrete log), p, q (Sophie Germain primes), +// N = (2p+1)(2q+1). +func generateDLNParams(t *testing.T) (h1, h2, x, p, q, N *big.Int) { + t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + + concurrency := runtime.NumCPU() + if concurrency < 1 { + concurrency = 1 + } + + // Generate two 1024-bit safe primes: safeP = 2p+1, safeQ = 2q+1 + sgps, err := common.GetRandomSafePrimesConcurrent(ctx, 1024, 2, concurrency, rand.Reader) + if err != nil { + t.Fatalf("failed to generate safe primes: %v", err) + } + + p = sgps[0].Prime() // Sophie Germain prime + q = sgps[1].Prime() // Sophie Germain prime + safeP := sgps[0].SafePrime() + safeQ := sgps[1].SafePrime() + N = new(big.Int).Mul(safeP, safeQ) + + modN := common.ModInt(N) + pMulQ := new(big.Int).Mul(p, q) + + // h1 = f^2 mod N (a quadratic residue) + f := common.GetRandomPositiveRelativelyPrimeInt(rand.Reader, N) + h1 = modN.Mul(f, f) + + // x = alpha, random coprime to N + alpha := common.GetRandomPositiveRelativelyPrimeInt(rand.Reader, N) + x = new(big.Int).Mod(alpha, pMulQ) + + // h2 = h1^x mod N + h2 = modN.Exp(h1, alpha) + + return +} + +func TestDLNProofVerifyHappyPath(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + if !proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("expected true") + } +} + +func TestDLNProofRejectsWrongSession(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + + if !proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("expected true") + } + if proof.Verify([]byte("wrong-session"), h1, h2, N) { + t.Fatal("expected false") + } +} + +func TestDLNProofRejectsSmallN(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + + // 1024-bit N is below the 2048-bit threshold. + smallN := new(big.Int).SetBit(new(big.Int), 1023, 1) + smallN.Add(smallN, big.NewInt(1)) + if proof.Verify(dlnSession, h1, h2, smallN) { + t.Fatal("small N should be rejected") + } +} + +func TestDLNProofRejectsNilN(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + if proof.Verify(dlnSession, h1, h2, nil) { + t.Fatal("nil N should be rejected") + } +} + +func TestDLNProofRejectsNilProof(t *testing.T) { + var proof *Proof + if proof.Verify(dlnSession, big.NewInt(3), big.NewInt(5), big.NewInt(15)) { + t.Fatal("expected false") + } +} + +func TestDLNProofRejectsTamperedAlpha(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + + if !proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("expected true") + } + + proof.Alpha[0] = new(big.Int).Add(proof.Alpha[0], big.NewInt(1)) + if proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("tampered Alpha should fail") + } +} + +func TestDLNProofRejectsEqualH1H2(t *testing.T) { + h1, _, _, _, _, N := generateDLNParams(t) + proof := &Proof{} + if proof.Verify(dlnSession, h1, h1, N) { + t.Fatal("expected false") + } +} + +func TestDLNProofRejectsNilAlphaElement(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + + proof.Alpha[0] = nil + if proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("nil Alpha element should be rejected") + } +} + +func TestDLNProofRejectsNilTElement(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + + proof.T[0] = nil + if proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("nil T element should be rejected") + } +} + +func TestDLNProofRejectsZeroN(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + if proof.Verify(dlnSession, h1, h2, big.NewInt(0)) { + t.Fatal("zero N should be rejected") + } +} + +func TestDLNProofRejectsNegativeN(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + negN := new(big.Int).Neg(N) + if proof.Verify(dlnSession, h1, h2, negN) { + t.Fatal("negative N should be rejected") + } +} + +func TestDLNProofRejectsH1EqualsOne(t *testing.T) { + _, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, big.NewInt(1), h2, x, p, q, N, rand.Reader) + if proof.Verify(dlnSession, big.NewInt(1), h2, N) { + t.Fatal("h1 == 1 should be rejected") + } +} + +func TestDLNProofNilSession(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(nil, h1, h2, x, p, q, N, rand.Reader) + if !proof.Verify(nil, h1, h2, N) { + t.Fatal("nil session proof should verify with nil session") + } + if proof.Verify(dlnSession, h1, h2, N) { + t.Fatal("nil session proof should not verify with non-nil session") + } +} + +func TestDLNProofSerializeRoundTrip(t *testing.T) { + h1, h2, x, p, q, N := generateDLNParams(t) + proof := NewDLNProof(dlnSession, h1, h2, x, p, q, N, rand.Reader) + + bzs, err := proof.Serialize() + if err != nil { + t.Fatal(err) + } + + recovered, err := UnmarshalDLNProof(bzs) + if err != nil { + t.Fatal(err) + } + + if !recovered.Verify(dlnSession, h1, h2, N) { + t.Fatal("deserialized proof should verify") + } +} diff --git a/tss-lib/crypto/ecpoint.go b/tss-lib/crypto/ecpoint.go index 5ea8aa9..064f5a1 100644 --- a/tss-lib/crypto/ecpoint.go +++ b/tss-lib/crypto/ecpoint.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package crypto @@ -18,7 +17,7 @@ import ( "github.com/decred/dcrd/dcrec/edwards/v2" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/tss" ) // ECPoint convenience helper @@ -55,13 +54,27 @@ func (p *ECPoint) Y() *big.Int { } func (p *ECPoint) Add(p1 *ECPoint) (*ECPoint, error) { + // [FORK] Upstream does not validate p1 before calling elliptic.Curve.Add. A nil p1 + // causes a nil-pointer panic, and mismatched curves silently miscompute. Added nil + // check and curve mismatch guard, and wrapped the result in NewECPoint for validation. + if p1 == nil { + return nil, fmt.Errorf("ECPoint.Add: p1 is nil") + } + if p.curve != p1.curve { + return nil, fmt.Errorf("ECPoint.Add: cannot add points on different curves") + } x, y := p.curve.Add(p.X(), p.Y(), p1.X(), p1.Y()) return NewECPoint(p.curve, x, y) } func (p *ECPoint) ScalarMult(k *big.Int) *ECPoint { x, y := p.curve.ScalarMult(p.X(), p.Y(), k.Bytes()) - newP, err := NewECPoint(p.curve, x, y) // it must be on the curve, no need to check. + // [FORK] Restored upstream panic behavior. Identity results (from zero scalar or + // group-order multiples) cause NewECPoint to reject (0,0) and panic. This is + // intentional: ~30 of 34 call sites do not check IsIdentity(), so silently + // returning identity would propagate bad math through the protocol. Pre-call + // guards at each site ensure the panic is unreachable in normal operation. + newP, err := NewECPoint(p.curve, x, y) if err != nil { panic(fmt.Errorf("scalar mult to an ecpoint %s", err.Error())) } @@ -91,6 +104,28 @@ func (p *ECPoint) Equals(p2 *ECPoint) bool { return p.X().Cmp(p2.X()) == 0 && p.Y().Cmp(p2.Y()) == 0 } +// [FORK] IsIdentity returns true if this point is the identity element (point at infinity). +// On Weierstrass curves (secp256k1, P-256, etc.), Go represents identity as (0, 0). +// On Edwards curves (edwards25519), the identity is (0, 1). +// New method added to support callers that need to detect identity results from +// ScalarMult/ScalarBaseMult. +func (p *ECPoint) IsIdentity() bool { + if p == nil { + return true + } + if p.coords[0].Sign() != 0 { + return false // x != 0 means definitely not identity on any curve + } + // x == 0: check y + if p.coords[1].Sign() == 0 { + return true // (0, 0) — Weierstrass identity + } + if p.coords[1].Cmp(big.NewInt(1)) == 0 { + return true // (0, 1) — Edwards identity + } + return false +} + func (p *ECPoint) SetCurve(curve elliptic.Curve) *ECPoint { p.curve = curve return p @@ -101,12 +136,28 @@ func (p *ECPoint) ValidateBasic() bool { } func (p *ECPoint) EightInvEight() *ECPoint { - return p.ScalarMult(eight).ScalarMult(eightInv) + // [FORK] Use raw curve.ScalarMult for the *8 step to detect torsion points without + // panicking. If p*8 = identity, the point is small-order; return identity directly. + // Callers' subsequent crypto checks (Schnorr verify, VSS verify) will reject it. + // CRITICAL: On Edwards25519 the identity is (0, 1), NOT (0, 0). Must use IsIdentity() + // — a raw x==0 && y==0 check would MISS the Edwards identity and the subsequent + // ScalarMult(eightInv) would panic on the identity input. + x, y := p.curve.ScalarMult(p.X(), p.Y(), eight.Bytes()) + tmp := NewECPointNoCurveCheck(p.curve, x, y) + if tmp.IsIdentity() { + return tmp + } + cleared, err := NewECPoint(p.curve, x, y) + if err != nil { + panic(fmt.Errorf("EightInvEight: intermediate point not on curve: %s", err.Error())) + } + return cleared.ScalarMult(eightInv) } func ScalarBaseMult(curve elliptic.Curve, k *big.Int) *ECPoint { x, y := curve.ScalarBaseMult(k.Bytes()) - p, err := NewECPoint(curve, x, y) // it must be on the curve, no need to check. + // [FORK] Restored upstream panic behavior. See ScalarMult comment for rationale. + p, err := NewECPoint(curve, x, y) if err != nil { panic(fmt.Errorf("scalar mult to an ecpoint %s", err.Error())) } @@ -145,12 +196,12 @@ func UnFlattenECPoints(curve elliptic.Curve, in []*big.Int, noCurveCheck ...bool unFlat := make([]*ECPoint, len(in)/2) for i, j := 0, 0; i < len(in); i, j = i+2, j+1 { if len(noCurveCheck) == 0 || !noCurveCheck[0] { - unFlat[j], err = NewECPoint(curve, in[i], in[i+1]) + unFlat[j], err = NewECPoint(curve, in[i], in[i+1]) //nolint:gosec // i+1 safe: len(in) is even, i increments by 2 if err != nil { return nil, err } } else { - unFlat[j] = NewECPointNoCurveCheck(curve, in[i], in[i+1]) + unFlat[j] = NewECPointNoCurveCheck(curve, in[i], in[i+1]) //nolint:gosec // i+1 safe: len(in) is even, i increments by 2 } } for _, point := range unFlat { @@ -175,12 +226,12 @@ func (p *ECPoint) GobEncode() ([]byte, error) { return nil, err } - err = binary.Write(buf, binary.LittleEndian, uint32(len(x))) + err = binary.Write(buf, binary.LittleEndian, uint32(len(x))) //nolint:gosec // big.Int coord bytes if err != nil { return nil, err } buf.Write(x) - err = binary.Write(buf, binary.LittleEndian, uint32(len(y))) + err = binary.Write(buf, binary.LittleEndian, uint32(len(y))) //nolint:gosec // big.Int coord bytes if err != nil { return nil, err } @@ -190,23 +241,32 @@ func (p *ECPoint) GobEncode() ([]byte, error) { } func (p *ECPoint) GobDecode(buf []byte) error { + // [FORK] Upstream has no length bound on decoded coordinates, allowing a crafted + // payload to allocate arbitrary memory. Cap at 1024 bytes (covers all standard curves). + const maxCoordLen = 1024 reader := bytes.NewReader(buf) var length uint32 if err := binary.Read(reader, binary.LittleEndian, &length); err != nil { return err } + if length > maxCoordLen { + return fmt.Errorf("gob decode failed: x coordinate length %d exceeds maximum %d", length, maxCoordLen) + } x := make([]byte, length) n, err := reader.Read(x) if n != int(length) || err != nil { - return fmt.Errorf("gob decode failed: %v", err) + return fmt.Errorf("gob decode failed: %w", err) } if err := binary.Read(reader, binary.LittleEndian, &length); err != nil { return err } + if length > maxCoordLen { + return fmt.Errorf("gob decode failed: y coordinate length %d exceeds maximum %d", length, maxCoordLen) + } y := make([]byte, length) n, err = reader.Read(y) if n != int(length) || err != nil { - return fmt.Errorf("gob decode failed: %v", err) + return fmt.Errorf("gob decode failed: %w", err) } X := new(big.Int) diff --git a/tss-lib/crypto/ecpoint_coverage_test.go b/tss-lib/crypto/ecpoint_coverage_test.go new file mode 100644 index 0000000..92b5757 --- /dev/null +++ b/tss-lib/crypto/ecpoint_coverage_test.go @@ -0,0 +1,140 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package crypto + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestEightInvEightIdentityPoint(t *testing.T) { + ec := tss.S256() + id := NewECPointNoCurveCheck(ec, big.NewInt(0), big.NewInt(0)) + if !id.IsIdentity() { + t.Fatal("(0,0) should be identity") + } + result := id.EightInvEight() + if !result.IsIdentity() { + t.Fatal("EightInvEight of identity should be identity") + } +} + +func TestNewECPointNilXY(t *testing.T) { + ec := tss.S256() + _, err := NewECPoint(ec, nil, big.NewInt(1)) + if err == nil { + t.Fatal("expected error for nil x") + } + _, err = NewECPoint(ec, big.NewInt(1), nil) + if err == nil { + t.Fatal("expected error for nil y") + } +} + +func TestUnFlattenBadPoint(t *testing.T) { + _, err := UnFlattenECPoints(tss.S256(), []*big.Int{big.NewInt(999), big.NewInt(999)}) + if err == nil { + t.Fatal("expected error for off-curve point") + } +} + +func TestUnFlattenNoCurveCheck(t *testing.T) { + pts, err := UnFlattenECPoints(tss.S256(), []*big.Int{big.NewInt(999), big.NewInt(999)}, true) + if err != nil { + t.Fatalf("noCurveCheck should not error: %v", err) + } + if len(pts) != 1 { + t.Fatalf("expected 1 point, got %d", len(pts)) + } +} + +func TestGobDecodeShortPayload(t *testing.T) { + p := new(ECPoint) + if err := p.GobDecode([]byte{1, 2}); err == nil { + t.Fatal("expected error for short data") + } +} + +func TestGobDecodeOversizedY(t *testing.T) { + ec := tss.S256() + pt := ScalarBaseMult(ec, big.NewInt(1)) + xBytes, _ := pt.X().GobEncode() + buf := &bytes.Buffer{} + _ = binary.Write(buf, binary.LittleEndian, uint32(len(xBytes))) //nolint:gosec // test data + buf.Write(xBytes) + _ = binary.Write(buf, binary.LittleEndian, uint32(2048)) + p := new(ECPoint) + if err := p.GobDecode(buf.Bytes()); err == nil { + t.Fatal("expected error for oversize y coordinate") + } +} + +func TestGobDecodeOffCurvePoint(t *testing.T) { + xBytes, _ := big.NewInt(999).GobEncode() + yBytes, _ := big.NewInt(999).GobEncode() + buf := &bytes.Buffer{} + _ = binary.Write(buf, binary.LittleEndian, uint32(len(xBytes))) //nolint:gosec // test data + buf.Write(xBytes) + _ = binary.Write(buf, binary.LittleEndian, uint32(len(yBytes))) //nolint:gosec // test data + buf.Write(yBytes) + p := new(ECPoint) + if err := p.GobDecode(buf.Bytes()); err == nil { + t.Fatal("expected error for off-curve point") + } +} + +func TestUnmarshalJSONBadJSON(t *testing.T) { + p := new(ECPoint) + if err := p.UnmarshalJSON([]byte("not json")); err == nil { + t.Fatal("expected error for bad JSON") + } +} + +func TestUnmarshalJSONBadCurveName(t *testing.T) { + payload := `{"Curve":"nonexistent","Coords":[1,2]}` + p := new(ECPoint) + if err := p.UnmarshalJSON([]byte(payload)); err == nil { + t.Fatal("expected error for unknown curve name") + } +} + +func TestUnmarshalJSONOffCurvePoint(t *testing.T) { + payload := `{"Curve":"secp256k1","Coords":[999,999]}` + p := new(ECPoint) + if err := p.UnmarshalJSON([]byte(payload)); err == nil { + t.Fatal("expected error for off-curve point") + } +} + +func TestMarshalJSONNilCurve(t *testing.T) { + p := NewECPointNoCurveCheck(nil, big.NewInt(1), big.NewInt(2)) + _, err := json.Marshal(p) + if err == nil { + t.Fatal("expected error for unregistered curve") + } +} + +func TestUnmarshalJSONEmptyCurveFallback(t *testing.T) { + ec := tss.S256() + p := ScalarBaseMult(ec, big.NewInt(42)) + data, _ := p.MarshalJSON() + var aux struct { + Curve string + Coords [2]*big.Int + } + _ = json.Unmarshal(data, &aux) + aux.Curve = "" + modified, _ := json.Marshal(aux) + + p2 := new(ECPoint) + if err := p2.UnmarshalJSON(modified); err != nil { + t.Fatalf("empty curve should use default: %v", err) + } +} diff --git a/tss-lib/crypto/ecpoint_fork_test.go b/tss-lib/crypto/ecpoint_fork_test.go new file mode 100644 index 0000000..0bce614 --- /dev/null +++ b/tss-lib/crypto/ecpoint_fork_test.go @@ -0,0 +1,147 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package crypto_test + +import ( + "encoding/binary" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestIsIdentityWeierstrass(t *testing.T) { + p := crypto.NewECPointNoCurveCheck(tss.S256(), big.NewInt(0), big.NewInt(0)) + if !p.IsIdentity() { + t.Fatal("Weierstrass identity (0,0) should be detected") + } +} + +func TestIsIdentityEdwards(t *testing.T) { + p := crypto.NewECPointNoCurveCheck(tss.Edwards(), big.NewInt(0), big.NewInt(1)) + if !p.IsIdentity() { + t.Fatal("Edwards identity (0,1) should be detected") + } +} + +func TestIsIdentityNonIdentity(t *testing.T) { + p := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + if p.IsIdentity() { + t.Fatal("a valid on-curve point should not be identity") + } +} + +func TestIsIdentityNilPoint(t *testing.T) { + var p *crypto.ECPoint + if !p.IsIdentity() { + t.Fatal("nil ECPoint should be treated as identity") + } +} + +func TestScalarMultByGroupOrder(t *testing.T) { + q := tss.S256().Params().N + g := crypto.ScalarBaseMult(tss.S256(), big.NewInt(1)) + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("G * q should panic (identity point)") + } + }() + g.ScalarMult(q) + }() +} + +func TestScalarBaseMultByZero(t *testing.T) { + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("ScalarBaseMult(0) should panic (identity point)") + } + }() + crypto.ScalarBaseMult(tss.S256(), big.NewInt(0)) + }() +} + +func TestAddNilP1(t *testing.T) { + p := crypto.ScalarBaseMult(tss.S256(), big.NewInt(7)) + _, err := p.Add(nil) + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "p1 is nil") { + t.Fatalf("expected %q to contain %q", err.Error(), "p1 is nil") + } +} + +func TestGobDecodeRejectsOversizedCoord(t *testing.T) { + // Craft a payload where X coordinate length prefix is 1025 (exceeds maxCoordLen=1024). + // Layout: uint32(xLen) | xBytes | uint32(yLen) | yBytes + const oversizedLen = 1025 + buf := make([]byte, 0, 4+oversizedLen+4+4) + + xLenBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(xLenBytes, uint32(oversizedLen)) + buf = append(buf, xLenBytes...) + buf = append(buf, make([]byte, oversizedLen)...) + + yLenBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(yLenBytes, uint32(4)) + buf = append(buf, yLenBytes...) + buf = append(buf, make([]byte, 4)...) + + p := &crypto.ECPoint{} + err := p.GobDecode(buf) + if err == nil { + t.Fatal("GobDecode should reject oversized coordinate") + } +} + +func TestGobDecodeAcceptsExactBoundaryCoord(t *testing.T) { + // Craft a payload where X coordinate length is exactly 1024 (the maxCoordLen boundary). + // The value is not a valid EC point, but GobDecode should NOT reject it due to size. + // It should fail for a different reason (e.g., big.Int GobDecode format or "not on curve"). + const exactLen = 1024 + buf := make([]byte, 0, 4+exactLen+4+4) + + xLenBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(xLenBytes, uint32(exactLen)) + buf = append(buf, xLenBytes...) + buf = append(buf, make([]byte, exactLen)...) + + yLenBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(yLenBytes, uint32(4)) + buf = append(buf, yLenBytes...) + buf = append(buf, make([]byte, 4)...) + + p := &crypto.ECPoint{} + err := p.GobDecode(buf) + // It may fail (invalid big.Int encoding, not on curve, etc.) but must NOT be the size check. + if err != nil { + if strings.Contains(err.Error(), "exceeds maximum") { + t.Fatal("1024-byte coordinate must not be rejected by the size check") + } + } +} + +func TestGobDecodeRoundTrip(t *testing.T) { + original := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + + encoded, err := original.GobEncode() + if err != nil { + t.Fatal(err) + } + + decoded := &crypto.ECPoint{} + err = decoded.GobDecode(encoded) + if err != nil { + t.Fatal(err) + } + + if !original.Equals(decoded) { + t.Fatal("round-tripped point should equal original") + } +} diff --git a/tss-lib/crypto/ecpoint_test.go b/tss-lib/crypto/ecpoint_test.go index a557057..698c885 100644 --- a/tss-lib/crypto/ecpoint_test.go +++ b/tss-lib/crypto/ecpoint_test.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package crypto_test @@ -15,10 +14,9 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/decred/dcrd/dcrec/edwards/v2" - "github.com/stretchr/testify/assert" - . "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/tss" + . "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" ) func TestFlattenECPoints(t *testing.T) { @@ -39,18 +37,22 @@ func TestFlattenECPoints(t *testing.T) { want: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4)}, }, { name: "flatten with nil point (expects err)", - args: args{[]*ECPoint{ - NewECPointNoCurveCheck(tss.EC(), big.NewInt(1), big.NewInt(2)), - nil, - NewECPointNoCurveCheck(tss.EC(), big.NewInt(3), big.NewInt(4))}, + args: args{ + []*ECPoint{ + NewECPointNoCurveCheck(tss.EC(), big.NewInt(1), big.NewInt(2)), + nil, + NewECPointNoCurveCheck(tss.EC(), big.NewInt(3), big.NewInt(4)), + }, }, want: nil, wantErr: true, }, { name: "flatten with nil coordinate (expects err)", - args: args{[]*ECPoint{ - NewECPointNoCurveCheck(tss.EC(), big.NewInt(1), big.NewInt(2)), - NewECPointNoCurveCheck(tss.EC(), nil, big.NewInt(4))}, + args: args{ + []*ECPoint{ + NewECPointNoCurveCheck(tss.EC(), big.NewInt(1), big.NewInt(2)), + NewECPointNoCurveCheck(tss.EC(), nil, big.NewInt(4)), + }, }, want: nil, wantErr: true, @@ -125,22 +127,38 @@ func TestS256EcpointJsonSerialization(t *testing.T) { tss.RegisterCurve("secp256k1", ec) pubKeyBytes, err := hex.DecodeString("03935336acb03b2b801d8f8ac5e92c56c4f6e93319901fdfffba9d340a874e2879") - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } pbk, err := btcec.ParsePubKey(pubKeyBytes) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } point, err := NewECPoint(ec, pbk.X(), pbk.Y()) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } bz, err := json.Marshal(point) - assert.NoError(t, err) - assert.True(t, len(bz) > 0) + if err != nil { + t.Fatal(err) + } + if !(len(bz) > 0) { + t.Fatal("expected true") + } var umpoint ECPoint err = json.Unmarshal(bz, &umpoint) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } - assert.True(t, point.Equals(&umpoint)) - assert.True(t, reflect.TypeOf(point.Curve()) == reflect.TypeOf(umpoint.Curve())) + if !point.Equals(&umpoint) { + t.Fatal("expected true") + } + if reflect.TypeOf(point.Curve()) != reflect.TypeOf(umpoint.Curve()) { + t.Fatal("expected true") + } } func TestEdwardsEcpointJsonSerialization(t *testing.T) { @@ -148,20 +166,36 @@ func TestEdwardsEcpointJsonSerialization(t *testing.T) { tss.RegisterCurve("ed25519", ec) pubKeyBytes, err := hex.DecodeString("ae1e5bf5f3d6bf58b5c222088671fcbe78b437e28fae944c793897b26091f249") - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } pbk, err := edwards.ParsePubKey(pubKeyBytes) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } point, err := NewECPoint(ec, pbk.X, pbk.Y) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } bz, err := json.Marshal(point) - assert.NoError(t, err) - assert.True(t, len(bz) > 0) + if err != nil { + t.Fatal(err) + } + if !(len(bz) > 0) { + t.Fatal("expected true") + } var umpoint ECPoint err = json.Unmarshal(bz, &umpoint) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } - assert.True(t, point.Equals(&umpoint)) - assert.True(t, reflect.TypeOf(point.Curve()) == reflect.TypeOf(umpoint.Curve())) + if !point.Equals(&umpoint) { + t.Fatal("expected true") + } + if reflect.TypeOf(point.Curve()) != reflect.TypeOf(umpoint.Curve()) { + t.Fatal("expected true") + } } diff --git a/tss-lib/crypto/facproof/negative_test.go b/tss-lib/crypto/facproof/negative_test.go new file mode 100644 index 0000000..29d1aeb --- /dev/null +++ b/tss-lib/crypto/facproof/negative_test.go @@ -0,0 +1,70 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package facproof + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +var negSession = []byte("facproof-neg-test") + +// --- Verify with wrong N0 --- + +func TestVerifyWrongN0(t *testing.T) { + ec := tss.EC() + N0p := common.GetRandomPrimeInt(rand.Reader, 512) + N0q := common.GetRandomPrimeInt(rand.Reader, 512) + N0 := new(big.Int).Mul(N0p, N0q) + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, 512), + common.GetRandomPrimeInt(rand.Reader, 512), + } + NCap, s, tt, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + t.Fatalf("GenerateNTildei: %v", err) + } + + proof, err := NewProof(negSession, ec, N0, NCap, s, tt, N0p, N0q, rand.Reader) + if err != nil { + t.Fatalf("NewProof: %v", err) + } + + wrongN0 := new(big.Int).Add(N0, big.NewInt(2)) + if proof.Verify(negSession, ec, wrongN0, NCap, s, tt) { + t.Fatal("proof should fail with wrong N0") + } +} + +// --- NewProofFromBytes truncated --- + +func TestNewProofFromBytesTruncated(t *testing.T) { + _, err := NewProofFromBytes([][]byte{{1}, {2}}) + if err == nil { + t.Fatal("expected error for truncated bytes") + } +} + +// --- ValidateBasic for RangeProofAlice/ProofBob --- +// These are tested via the mta tests already, but let's test NewProof error (nil N0) + +func TestNewProofNilN0(t *testing.T) { + ec := tss.EC() + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, 512), + common.GetRandomPrimeInt(rand.Reader, 512), + } + NCap, s, tt, _ := crypto.GenerateNTildei(rand.Reader, primes) + _, err := NewProof(negSession, ec, nil, NCap, s, tt, big.NewInt(3), big.NewInt(5), rand.Reader) + if err == nil { + t.Fatal("expected error for nil N0") + } +} diff --git a/tss-lib/crypto/facproof/proof.go b/tss-lib/crypto/facproof/proof.go index 09ed858..1f12fd3 100644 --- a/tss-lib/crypto/facproof/proof.go +++ b/tss-lib/crypto/facproof/proof.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package facproof @@ -13,7 +12,7 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) const ( @@ -26,13 +25,7 @@ type ( } ) -var ( - // rangeParameter l limits the bits of p or q to be in [1024-l, 1024+l] - rangeParameter = new(big.Int).Lsh(big.NewInt(1), 15) - one = big.NewInt(1) -) - -// NewProof implements prooffac +// NewProof implements prooffac. Session provides SSID domain separation (replay prevention). func NewProof(Session []byte, ec elliptic.Curve, N0, NCap, s, t, N0p, N0q *big.Int, rand io.Reader) (*ProofFac, error) { if ec == nil || N0 == nil || NCap == nil || s == nil || t == nil || N0p == nil || N0q == nil { return nil, errors.New("ProveFac constructor received nil value(s)") @@ -107,18 +100,36 @@ func NewProofFromBytes(bzs [][]byte) (*ProofFac, error) { if !common.NonEmptyMultiBytes(bzs, ProofFacBytesParts) { return nil, fmt.Errorf("expected %d byte parts to construct ProofFac", ProofFacBytesParts) } + // [FORK] V uses sign-magnitude encoding: first byte is 0x00 (positive) or 0x01 (negative). + // Upstream uses SetBytes which cannot represent negative V, silently truncating + // to |V| and causing verification failures for ~50% of honest proofs. + vBz := bzs[10] //nolint:gosec // len(bzs) >= 11 checked above + if len(vBz) < 1 { + return nil, fmt.Errorf("v field too short for sign-magnitude decoding") + } + vSign := vBz[0] + if vSign != 0x00 && vSign != 0x01 { + return nil, fmt.Errorf("invalid V sign byte: 0x%02x", vSign) + } + vAbs := new(big.Int).SetBytes(vBz[1:]) + if vSign == 0x01 { + if vAbs.Sign() == 0 { + return nil, fmt.Errorf("negative zero V encoding is not canonical") + } + vAbs.Neg(vAbs) + } return &ProofFac{ - P: new(big.Int).SetBytes(bzs[0]), - Q: new(big.Int).SetBytes(bzs[1]), - A: new(big.Int).SetBytes(bzs[2]), - B: new(big.Int).SetBytes(bzs[3]), - T: new(big.Int).SetBytes(bzs[4]), - Sigma: new(big.Int).SetBytes(bzs[5]), - Z1: new(big.Int).SetBytes(bzs[6]), - Z2: new(big.Int).SetBytes(bzs[7]), - W1: new(big.Int).SetBytes(bzs[8]), - W2: new(big.Int).SetBytes(bzs[9]), - V: new(big.Int).SetBytes(bzs[10]), + P: new(big.Int).SetBytes(bzs[0]), //nolint:gosec // guarded by NonEmptyMultiBytes + Q: new(big.Int).SetBytes(bzs[1]), //nolint:gosec // guarded by NonEmptyMultiBytes + A: new(big.Int).SetBytes(bzs[2]), //nolint:gosec // guarded by NonEmptyMultiBytes + B: new(big.Int).SetBytes(bzs[3]), //nolint:gosec // guarded by NonEmptyMultiBytes + T: new(big.Int).SetBytes(bzs[4]), //nolint:gosec // guarded by NonEmptyMultiBytes + Sigma: new(big.Int).SetBytes(bzs[5]), //nolint:gosec // guarded by NonEmptyMultiBytes + Z1: new(big.Int).SetBytes(bzs[6]), //nolint:gosec // guarded by NonEmptyMultiBytes + Z2: new(big.Int).SetBytes(bzs[7]), //nolint:gosec // guarded by NonEmptyMultiBytes + W1: new(big.Int).SetBytes(bzs[8]), //nolint:gosec // guarded by NonEmptyMultiBytes + W2: new(big.Int).SetBytes(bzs[9]), //nolint:gosec // guarded by NonEmptyMultiBytes + V: vAbs, }, nil } @@ -129,6 +140,16 @@ func (pf *ProofFac) Verify(Session []byte, ec elliptic.Curve, N0, NCap, s, t *bi if N0.Sign() != 1 { return false } + // [FORK] Reject undersized moduli — FacProof is only sound when N0 is the + // product of two large primes (>= 2048-bit modulus). Upstream does not check. + if N0.BitLen() < 2048 { + return false + } + // [FORK] NCap (the Pedersen commitment modulus) must also be sufficiently large. + // Upstream does not check. + if NCap.BitLen() < 2048 { + return false + } q := ec.Params().N q3 := new(big.Int).Mul(q, q) @@ -173,7 +194,21 @@ func (pf *ProofFac) Verify(Session []byte, ec elliptic.Curve, N0, NCap, s, t *bi { R := modNCap.Mul(modNCap.Exp(s, N0), modNCap.Exp(t, pf.Sigma)) - LHS := modNCap.Mul(modNCap.Exp(pf.Q, pf.Z1), modNCap.Exp(t, pf.V)) + // [FORK] V can be negative (v = e*(sigma - nu*p) + r). Upstream silently drops the + // sign via SetBytes, causing ~50% of honest proofs to fail. We handle negative + // exponents explicitly: compute t^(-1) mod NCap then raise to |V|. The nil check + // on tInv prevents a panic if t is not invertible mod NCap. + var tExpV *big.Int + if pf.V.Sign() < 0 { + tInv := modNCap.ModInverse(t) + if tInv == nil { + return false // t not invertible mod NCap + } + tExpV = modNCap.Exp(tInv, new(big.Int).Abs(pf.V)) + } else { + tExpV = modNCap.Exp(t, pf.V) + } + LHS := modNCap.Mul(modNCap.Exp(pf.Q, pf.Z1), tExpV) RHS := modNCap.Mul(pf.T, modNCap.Exp(R, e)) if LHS.Cmp(RHS) != 0 { @@ -199,6 +234,15 @@ func (pf *ProofFac) ValidateBasic() bool { } func (pf *ProofFac) Bytes() [ProofFacBytesParts][]byte { + // [FORK] V can be negative (v = e*(sigma - nu*p) + r). Use sign-magnitude + // encoding: prefix 0x00 for non-negative, 0x01 for negative. + // Upstream uses big.Int.Bytes() which discards the sign, corrupting negative values. + vBytes := pf.V.Bytes() + if pf.V.Sign() < 0 { + vBytes = append([]byte{0x01}, vBytes...) + } else { + vBytes = append([]byte{0x00}, vBytes...) + } return [...][]byte{ pf.P.Bytes(), pf.Q.Bytes(), @@ -210,6 +254,6 @@ func (pf *ProofFac) Bytes() [ProofFacBytesParts][]byte { pf.Z2.Bytes(), pf.W1.Bytes(), pf.W2.Bytes(), - pf.V.Bytes(), + vBytes, } } diff --git a/tss-lib/crypto/facproof/proof_fork_test.go b/tss-lib/crypto/facproof/proof_fork_test.go new file mode 100644 index 0000000..e9b35a2 --- /dev/null +++ b/tss-lib/crypto/facproof/proof_fork_test.go @@ -0,0 +1,236 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Tests for FacProof fork changes: SSID session domain separation, +// V sign-magnitude encoding, N0/NCap BitLen < 2048 rejection. + +package facproof + +import ( + "context" + "crypto/rand" + "math/big" + "reflect" + "strings" + "testing" + "time" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +var forkSession = []byte("facproof-fork-test") + +// generateFacProofFixture generates a complete facproof fixture with real +// Paillier keys and Pedersen parameters. Returns (proof, N0, NCap, s, t). +func generateFacProofFixture(t *testing.T) (*ProofFac, *big.Int, *big.Int, *big.Int, *big.Int) { + t.Helper() + ec := tss.EC() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + + // Generate Paillier keypair for N0. + sk, _, err := paillier.GenerateKeyPair(ctx, rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + N0 := sk.N + N0p := sk.P + N0q := sk.Q + + // Generate Pedersen parameters (NCap, s, t). + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, 1024), + common.GetRandomPrimeInt(rand.Reader, 1024), + } + NCap, s, tt, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + t.Fatal(err) + } + + proof, err := NewProof(forkSession, ec, N0, NCap, s, tt, N0p, N0q, rand.Reader) + if err != nil { + t.Fatal(err) + } + + return proof, N0, NCap, s, tt +} + +func TestFacProofForkVerifyHappyPath(t *testing.T) { + proof, N0, NCap, s, tt := generateFacProofFixture(t) + if !(proof.Verify(forkSession, tss.EC(), N0, NCap, s, tt)) { + t.Fatal("expected true") + } +} + +func TestFacProofForkRejectsWrongSession(t *testing.T) { + proof, N0, NCap, s, tt := generateFacProofFixture(t) + if !(proof.Verify(forkSession, tss.EC(), N0, NCap, s, tt)) { + t.Fatal("expected true") + } + if proof.Verify([]byte("wrong-session"), tss.EC(), N0, NCap, s, tt) { + t.Fatal("expected false") + } +} + +func TestFacProofForkVSignMagnitudeRoundTrip(t *testing.T) { + // [FORK] V can be negative. Test Bytes()/NewProofFromBytes() round-trip. + proof, N0, NCap, s, tt := generateFacProofFixture(t) + + // Serialize and deserialize. + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + t.Fatal(err) + } + + // All fields should match. + if proof.P.Cmp(recovered.P) != 0 { + t.Fatalf("P mismatch") + } + if proof.Q.Cmp(recovered.Q) != 0 { + t.Fatalf("Q mismatch") + } + if proof.V.Cmp(recovered.V) != 0 { + t.Fatalf("V mismatch (sign-magnitude)") + } + if !reflect.DeepEqual(proof.V.Sign(), recovered.V.Sign()) { + t.Fatalf("V sign mismatch") + } + + // Recovered proof should still verify. + if !(recovered.Verify(forkSession, tss.EC(), N0, NCap, s, tt)) { + t.Fatal("expected true") + } +} + +func TestFacProofForkRejectsSmallN0(t *testing.T) { + // [FORK] N0.BitLen() < 2048 should be rejected. + proof, _, NCap, s, tt := generateFacProofFixture(t) + smallN0 := common.GetRandomPrimeInt(rand.Reader, 512) + if proof.Verify(forkSession, tss.EC(), smallN0, NCap, s, tt) { + t.Fatal("expected false") + } +} + +func TestFacProofForkRejectsSmallNCap(t *testing.T) { + // [FORK] NCap.BitLen() < 2048 should be rejected. + proof, N0, _, s, tt := generateFacProofFixture(t) + smallNCap := common.GetRandomPrimeInt(rand.Reader, 512) + if proof.Verify(forkSession, tss.EC(), N0, smallNCap, s, tt) { + t.Fatal("expected false") + } +} + +func TestFacProofForkFromBytesRejectsInvalidVSign(t *testing.T) { + proof, _, _, _, _ := generateFacProofFixture(t) + bzs := proof.Bytes() + + // Tamper the V sign byte to an invalid value. + original := bzs[10] + tampered := make([]byte, len(original)) + copy(tampered, original) + tampered[0] = 0x02 // invalid sign byte (must be 0x00 or 0x01) + bzs[10] = tampered + + _, err := NewProofFromBytes(bzs[:]) + if err == nil { + t.Fatal("invalid V sign byte should error") + } + if !strings.Contains(err.Error(), "sign byte") { + t.Fatalf("expected %q to contain %q", err.Error(), "sign byte") + } +} + +func TestFacProofForkFromBytesRejectsNegativeZero(t *testing.T) { + proof, _, _, _, _ := generateFacProofFixture(t) + bzs := proof.Bytes() + + // Craft a V field that encodes "negative zero" (sign=0x01, no magnitude bytes = zero). + bzs[10] = []byte{0x01} + + _, err := NewProofFromBytes(bzs[:]) + if err == nil { + t.Fatal("negative zero V should error") + } +} + +func TestFacProofForkRejectsNilProof(t *testing.T) { + var proof *ProofFac + if proof.Verify(forkSession, tss.EC(), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)) { + t.Fatal("expected false") + } +} + +func TestFacProofForkRejectsNilN0(t *testing.T) { + proof, _, NCap, s, tt := generateFacProofFixture(t) + if proof.Verify(forkSession, tss.EC(), nil, NCap, s, tt) { + t.Fatal("nil N0 should be rejected") + } +} + +func TestFacProofForkRejectsNilNCap(t *testing.T) { + proof, N0, _, s, tt := generateFacProofFixture(t) + if proof.Verify(forkSession, tss.EC(), N0, nil, s, tt) { + t.Fatal("nil NCap should be rejected") + } +} + +func TestFacProofForkRejectsNilEC(t *testing.T) { + proof, N0, NCap, s, tt := generateFacProofFixture(t) + if proof.Verify(forkSession, nil, N0, NCap, s, tt) { + t.Fatal("nil EC should be rejected") + } +} + +func TestFacProofForkNilSession(t *testing.T) { + ec := tss.EC() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + + sk, _, err := paillier.GenerateKeyPair(ctx, rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + N0 := sk.N + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, 1024), + common.GetRandomPrimeInt(rand.Reader, 1024), + } + NCap, s, tt, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + t.Fatal(err) + } + + // A nil session should produce a valid proof that verifies with nil session + // but fails with a different session. + proof, err := NewProof(nil, ec, N0, NCap, s, tt, sk.P, sk.Q, rand.Reader) + if err != nil { + t.Fatal(err) + } + if !proof.Verify(nil, ec, N0, NCap, s, tt) { + t.Fatal("nil session proof should verify with nil session") + } + if proof.Verify(forkSession, ec, N0, NCap, s, tt) { + t.Fatal("nil session proof should not verify with non-nil session") + } +} + +func TestFacProofForkRejectsZeroN0(t *testing.T) { + proof, _, NCap, s, tt := generateFacProofFixture(t) + if proof.Verify(forkSession, tss.EC(), big.NewInt(0), NCap, s, tt) { + t.Fatal("zero N0 should be rejected") + } +} + +func TestFacProofForkRejectsNegativeN0(t *testing.T) { + proof, N0, NCap, s, tt := generateFacProofFixture(t) + negN0 := new(big.Int).Neg(N0) + if proof.Verify(forkSession, tss.EC(), negN0, NCap, s, tt) { + t.Fatal("negative N0 should be rejected") + } +} diff --git a/tss-lib/crypto/facproof/proof_test.go b/tss-lib/crypto/facproof/proof_test.go index 4ce90b5..d503e0c 100644 --- a/tss-lib/crypto/facproof/proof_test.go +++ b/tss-lib/crypto/facproof/proof_test.go @@ -1,22 +1,20 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package facproof_test import ( "crypto/rand" "math/big" + "reflect" "testing" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - . "github.com/hemilabs/x/tss-lib/v2/crypto/facproof" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + . "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/tss" ) // Using a modulus length of 2048 is recommended in the GG18 spec @@ -35,20 +33,586 @@ func TestFac(test *testing.T) { primes := [2]*big.Int{common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits)} NCap, s, t, err := crypto.GenerateNTildei(rand.Reader, primes) - assert.NoError(test, err) + if err != nil { + test.Fatal(err) + } proof, err := NewProof(Session, ec, N0, NCap, s, t, N0p, N0q, rand.Reader) - assert.NoError(test, err) + if err != nil { + test.Fatal(err) + } ok := proof.Verify(Session, ec, N0, NCap, s, t) - assert.True(test, ok, "proof must verify") + if !ok { + test.Fatal("proof must verify") + } N0p = common.GetRandomPrimeInt(rand.Reader, 1024) N0q = common.GetRandomPrimeInt(rand.Reader, 1024) N0 = new(big.Int).Mul(N0p, N0q) proof, err = NewProof(Session, ec, N0, NCap, s, t, N0p, N0q, rand.Reader) - assert.NoError(test, err) + if err != nil { + test.Fatal(err) + } ok = proof.Verify(Session, ec, N0, NCap, s, t) - assert.True(test, ok, "proof must verify") + if !ok { + test.Fatal("proof must verify") + } +} + +// TestFacProofBytesRoundTrip verifies that Bytes() -> NewProofFromBytes() preserves +// all fields including the sign of V. +func TestFacProofBytesRoundTrip(test *testing.T) { + ec := tss.EC() + + N0p := common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits) + N0q := common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits) + N0 := new(big.Int).Mul(N0p, N0q) + + primes := [2]*big.Int{common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits)} + NCap, s, t, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + test.Fatal(err) + } + + proof, err := NewProof(Session, ec, N0, NCap, s, t, N0p, N0q, rand.Reader) + if err != nil { + test.Fatal(err) + } + + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatal(err) + } + + // All fields must match exactly. + if !reflect.DeepEqual(proof.P, recovered.P) { + test.Fatalf("P mismatch") + } + if !reflect.DeepEqual(proof.Q, recovered.Q) { + test.Fatalf("Q mismatch") + } + if !reflect.DeepEqual(proof.A, recovered.A) { + test.Fatalf("A mismatch") + } + if !reflect.DeepEqual(proof.B, recovered.B) { + test.Fatalf("B mismatch") + } + if !reflect.DeepEqual(proof.T, recovered.T) { + test.Fatalf("T mismatch") + } + if !reflect.DeepEqual(proof.Sigma, recovered.Sigma) { + test.Fatalf("Sigma mismatch") + } + if !reflect.DeepEqual(proof.Z1, recovered.Z1) { + test.Fatalf("Z1 mismatch") + } + if !reflect.DeepEqual(proof.Z2, recovered.Z2) { + test.Fatalf("Z2 mismatch") + } + if !reflect.DeepEqual(proof.W1, recovered.W1) { + test.Fatalf("W1 mismatch") + } + if !reflect.DeepEqual(proof.W2, recovered.W2) { + test.Fatalf("W2 mismatch") + } + if !reflect.DeepEqual(proof.V, recovered.V) { + test.Fatalf("V mismatch") + } + + // Recovered proof must also verify. + ok := recovered.Verify(Session, ec, N0, NCap, s, t) + if !ok { + test.Fatal("recovered proof must verify") + } +} + +// TestFacProofVSignMagnitudeNegative verifies that a negative V is preserved +// through the sign-magnitude encoding. +func TestFacProofVSignMagnitudeNegative(test *testing.T) { + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: big.NewInt(-42), + } + + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatal(err) + } + if !reflect.DeepEqual(big.NewInt(-42), recovered.V) { + test.Fatalf("negative V must survive round-trip") + } + if recovered.V.Sign() != -1 { + test.Fatalf("V sign must be negative") + } +} + +// TestFacProofVSignMagnitudePositive verifies that a positive V is preserved. +func TestFacProofVSignMagnitudePositive(test *testing.T) { + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: big.NewInt(42), + } + + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatal(err) + } + if !reflect.DeepEqual(big.NewInt(42), recovered.V) { + test.Fatalf("positive V must survive round-trip") + } + if recovered.V.Sign() != 1 { + test.Fatalf("V sign must be positive") + } +} + +// TestFacProofVSignMagnitudeZero verifies that zero V is preserved. +func TestFacProofVSignMagnitudeZero(test *testing.T) { + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: big.NewInt(0), + } + + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatal(err) + } + if recovered.V.Sign() != 0 { + test.Fatalf("zero V must survive round-trip") + } +} + +// TestFacProofVSignMagnitudeLargeNegative tests a large negative V value. +func TestFacProofVSignMagnitudeLargeNegative(test *testing.T) { + largeNeg := new(big.Int).SetBytes(make([]byte, 256)) // 2048-bit + largeNeg.SetBit(largeNeg, 2047, 1) // Set high bit + largeNeg.Neg(largeNeg) // Make negative + + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: largeNeg, + } + + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatal(err) + } + if largeNeg.Cmp(recovered.V) != 0 { + test.Fatalf("large negative V must survive round-trip") + } +} + +// TestFacProofFromBytesTruncated verifies that truncated input produces an error. +func TestFacProofFromBytesTruncated(test *testing.T) { + // Only 5 parts instead of 11. + truncated := make([][]byte, 5) + for i := range truncated { + truncated[i] = []byte{0x01} + } + _, err := NewProofFromBytes(truncated) + if err == nil { + test.Fatal("truncated input should error") + } +} + +// TestFacProofFromBytesEmptyV verifies that empty V field produces an error. +func TestFacProofFromBytesEmptyV(test *testing.T) { + parts := make([][]byte, ProofFacBytesParts) + for i := range parts { + parts[i] = []byte{0x01} + } + // V field (index 10) is empty. + parts[10] = []byte{} + _, err := NewProofFromBytes(parts) + if err == nil { + test.Fatal("empty V should error") + } +} + +// TestFacProofFromBytesInvalidSignByte verifies that non-canonical sign bytes are rejected. +func TestFacProofFromBytesInvalidSignByte(test *testing.T) { + for _, badSign := range []byte{0x02, 0x03, 0xFF, 0x80} { + parts := make([][]byte, ProofFacBytesParts) + for i := range parts { + parts[i] = []byte{0x01} + } + // V field with invalid sign byte prefix. + parts[10] = []byte{badSign, 0x2A} // sign=badSign, magnitude=42 + _, err := NewProofFromBytes(parts) + if err == nil { + test.Fatal("sign byte 0x%02x should be rejected", badSign) + } + } +} + +// TestFacProofFromBytesNegativeZero verifies that negative-zero encoding is rejected. +func TestFacProofFromBytesNegativeZero(test *testing.T) { + parts := make([][]byte, ProofFacBytesParts) + for i := range parts { + parts[i] = []byte{0x01} + } + // V field: sign=negative(0x01), magnitude=empty (zero). + parts[10] = []byte{0x01} + _, err := NewProofFromBytes(parts) + if err == nil { + test.Fatal("negative zero V should be rejected") + } +} + +// TestFacProofFromBytesExtraParts verifies that too many parts are rejected. +func TestFacProofFromBytesExtraParts(test *testing.T) { + parts := make([][]byte, ProofFacBytesParts+1) + for i := range parts { + parts[i] = []byte{0x01} + } + _, err := NewProofFromBytes(parts) + if err == nil { + test.Fatal("extra parts should be rejected") + } +} + +// TestFacProofVerifyNegativeVNoPanic verifies that Verify does not panic +// when V is negative. This is the critical fix for the big.Int.Exp panic. +func TestFacProofVerifyNegativeVNoPanic(test *testing.T) { + ec := tss.EC() + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NCap, s, t, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + test.Fatal(err) + } + + // Construct a proof with negative V and verify it doesn't panic. + // The proof won't pass verification (since it's hand-crafted), but + // it MUST NOT panic. + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: big.NewInt(-42), + } + // Must not panic -- this was the critical bug (big.Int.Exp panics + // with negative exponent + non-nil modulus in Go 1.13+). + func() { + defer func() { + if r := recover(); r != nil { + test.Fatalf("unexpected panic: %v", r) + } + }() + proof.Verify(Session, ec, big.NewInt(100), NCap, s, t) + }() +} + +// TestFacProofVerifyNegativeVRealProof generates real proofs until one has +// negative V, then verifies it survives a round-trip and passes verification. +func TestFacProofVerifyNegativeVRealProof(test *testing.T) { + ec := tss.EC() + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NCap, s, t, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + test.Fatal(err) + } + + // Generate proofs until we find one with negative V, up to 100 attempts. + foundNegative := false + for i := 0; i < 100; i++ { + N0p := common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits) + N0q := common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits) + N0 := new(big.Int).Mul(N0p, N0q) + + proof, err := NewProof(Session, ec, N0, NCap, s, t, N0p, N0q, rand.Reader) + if err != nil { + test.Fatal(err) + } + + if proof.V.Sign() < 0 { + foundNegative = true + test.Logf("Found negative V at iteration %d: %s", i, proof.V) + + // Must verify directly. + ok := proof.Verify(Session, ec, N0, NCap, s, t) + if !ok { + test.Fatal("proof with negative V must verify") + } + + // Must survive round-trip. + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatal(err) + } + if !reflect.DeepEqual(proof.V.Sign(), recovered.V.Sign()) { + test.Fatalf("got %v, want %v", recovered.V.Sign(), proof.V.Sign()) + } + + ok = recovered.Verify(Session, ec, N0, NCap, s, t) + if !ok { + test.Fatal("recovered proof with negative V must verify") + } + break + } + } + if !foundNegative { + test.Skip("No negative V found in 100 iterations (rare but possible); skipping") + } +} + +// TestFacProofVerifyNegativeVMathCorrectness verifies the mathematical correctness +// of the negative-V fix using known values: t^{-V} mod NCap = (t^{-1})^{|V|} mod NCap. +func TestFacProofVerifyNegativeVMathCorrectness(test *testing.T) { + NCap := big.NewInt(221) // 13 * 17 + t_ := big.NewInt(5) // coprime to 221 + V := big.NewInt(-7) + + // Method 1 (old, panics): t^V mod NCap -- cannot use big.Int.Exp + // Method 2 (new fix): (t^{-1})^{|V|} mod NCap + tInv := new(big.Int).ModInverse(t_, NCap) // 5^{-1} mod 221 + if tInv == nil { + test.Fatal("t not invertible mod NCap") + } + result := new(big.Int).Exp(tInv, new(big.Int).Abs(V), NCap) + + // Verify independently: t^7 mod NCap, then check (t^7)*(t^{-7}) = 1 mod NCap. + tPosExp := new(big.Int).Exp(t_, big.NewInt(7), NCap) + product := new(big.Int).Mul(tPosExp, result) + product.Mod(product, NCap) + if product.Cmp(big.NewInt(1)) != 0 { + test.Fatalf("t^7 * t^{-7} mod NCap = %s, want 1", product) + } + + test.Logf("t^{-1} mod %d = %s", NCap, tInv) + test.Logf("(t^{-1})^7 mod %d = %s", NCap, result) + test.Logf("t^7 * (t^{-1})^7 mod %d = %s (should be 1)", NCap, product) +} + +// TestFacProofMultipleRoundTripsVerify generates multiple real proofs, serializes +// and deserializes each, and verifies all still pass. This catches any sign-dependent +// verification failure under real conditions. +func TestFacProofMultipleRoundTripsVerify(test *testing.T) { + ec := tss.EC() + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NCap, s, t, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + test.Fatal(err) + } + + for i := 0; i < 10; i++ { + N0p := common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits) + N0q := common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits) + N0 := new(big.Int).Mul(N0p, N0q) + + proof, err := NewProof(Session, ec, N0, NCap, s, t, N0p, N0q, rand.Reader) + if err != nil { + test.Fatalf("iteration %d: NewProof failed: %v", i, err) + } + + // Serialize and deserialize. + bzs := proof.Bytes() + recovered, err := NewProofFromBytes(bzs[:]) + if err != nil { + test.Fatalf("iteration %d: NewProofFromBytes failed: %v", i, err) + } + + // V sign must be preserved. + if !reflect.DeepEqual(proof.V.Sign(), recovered.V.Sign()) { + test.Fatalf("iteration %d: V sign changed after round-trip (original=%s, recovered=%s)", i, proof.V, recovered.V) + } + + // Recovered proof must verify. + ok := recovered.Verify(Session, ec, N0, NCap, s, t) + if !ok { + test.Fatalf("iteration %d: recovered proof failed verification", i) + } + } +} + +// TestFacProofBytesVSignGoldenVector verifies the exact sign-magnitude encoding +// of the V field (index 10) for known values: positive, negative, and zero. +func TestFacProofBytesVSignGoldenVector(test *testing.T) { + makeProof := func(v *big.Int) *ProofFac { + return &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: v, + } + } + + // V = 42: sign byte 0x00 (positive) + magnitude 0x2a + bzs42 := makeProof(big.NewInt(42)).Bytes() + if !reflect.DeepEqual([]byte{0x00, 0x2a}, bzs42[10]) { + test.Fatalf("V=42 should encode as [0x00, 0x2a]") + } + + // V = -42: sign byte 0x01 (negative) + magnitude 0x2a + bzsNeg42 := makeProof(big.NewInt(-42)).Bytes() + if !reflect.DeepEqual([]byte{0x01, 0x2a}, bzsNeg42[10]) { + test.Fatalf("V=-42 should encode as [0x01, 0x2a]") + } + + // V = 0: sign byte 0x00 (positive) + empty magnitude + bzs0 := makeProof(big.NewInt(0)).Bytes() + if !reflect.DeepEqual([]byte{0x00}, bzs0[10]) { + test.Fatalf("V=0 should encode as [0x00]") + } +} + +// TestFacProofFromBytesOldFormatNoSignByte verifies that the old format (raw +// magnitude with no sign prefix) is rejected. A raw byte 0x2a is not a valid +// sign byte (must be 0x00 or 0x01), so NewProofFromBytes should return an error. +func TestFacProofFromBytesOldFormatNoSignByte(test *testing.T) { + parts := make([][]byte, ProofFacBytesParts) + for i := range parts { + parts[i] = []byte{0x01} + } + // V field: raw magnitude 0x2a without sign prefix (old format). + // The first byte 0x2a will be interpreted as the sign byte, + // which is invalid (not 0x00 or 0x01). + parts[10] = []byte{0x2a} + _, err := NewProofFromBytes(parts) + if err == nil { + test.Fatal("old-format V (no sign byte) should be rejected") + } +} + +// TestFacProofFromBytesNilInput verifies that nil input returns an error. +func TestFacProofFromBytesNilInput(test *testing.T) { + _, err := NewProofFromBytes(nil) + if err == nil { + test.Fatal("nil input should return error") + } +} + +// TestFacProofFromBytesWrongPartCount verifies that providing fewer than +// ProofFacBytesParts (11) parts returns an error. +func TestFacProofFromBytesWrongPartCount(test *testing.T) { + parts := make([][]byte, 10) // one fewer than required (11) + for i := range parts { + parts[i] = []byte{0x01} + } + _, err := NewProofFromBytes(parts) + if err == nil { + test.Fatal("10 parts instead of 11 should return error") + } +} + +// TestFacProofValidateBasicNilFields verifies that ValidateBasic returns false +// when any individual field is nil. +func TestFacProofValidateBasicNilFields(test *testing.T) { + fields := []string{"P", "Q", "A", "B", "T", "Sigma", "Z1", "Z2", "W1", "W2", "V"} + for i, name := range fields { + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: big.NewInt(11), + } + // Set field i to nil using reflection-like approach via index. + switch i { + case 0: + proof.P = nil + case 1: + proof.Q = nil + case 2: + proof.A = nil + case 3: + proof.B = nil + case 4: + proof.T = nil + case 5: + proof.Sigma = nil + case 6: + proof.Z1 = nil + case 7: + proof.Z2 = nil + case 8: + proof.W1 = nil + case 9: + proof.W2 = nil + case 10: + proof.V = nil + } + if proof.ValidateBasic() { + test.Fatalf("ValidateBasic should return false when %s is nil", name) + } + } +} + +// TestFacProofValidateBasicAllNonNil verifies that ValidateBasic returns true +// when all fields are non-nil. +func TestFacProofValidateBasicAllNonNil(test *testing.T) { + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(7), Z2: big.NewInt(8), + W1: big.NewInt(9), W2: big.NewInt(10), + V: big.NewInt(11), + } + if !proof.ValidateBasic() { + test.Fatal("ValidateBasic should return true for all non-nil fields") + } +} + +// TestFacProofVerifyNonInvertibleT verifies that Verify returns false (not panic) +// when t is not invertible mod NCap and V is negative. +func TestFacProofVerifyNonInvertibleT(test *testing.T) { + ec := tss.EC() + + // Use NCap = 6 and t = 2, which are not coprime (gcd(2,6)=2). + NCap := big.NewInt(6) + s := big.NewInt(1) + t_ := big.NewInt(2) // not invertible mod 6 + + proof := &ProofFac{ + P: big.NewInt(1), Q: big.NewInt(2), A: big.NewInt(3), + B: big.NewInt(4), T: big.NewInt(5), Sigma: big.NewInt(6), + Z1: big.NewInt(1), Z2: big.NewInt(1), + W1: big.NewInt(1), W2: big.NewInt(1), + V: big.NewInt(-42), // negative V to trigger the tInv path + } + + // Must not panic — should return false because t is not invertible mod NCap. + func() { + defer func() { + if r := recover(); r != nil { + test.Fatalf("unexpected panic: %v", r) + } + }() + result := proof.Verify(Session, ec, big.NewInt(100), NCap, s, t_) + if result { + test.Fatal("Verify should return false for non-invertible t") + } + }() } diff --git a/tss-lib/crypto/modproof/negative_test.go b/tss-lib/crypto/modproof/negative_test.go new file mode 100644 index 0000000..2d27469 --- /dev/null +++ b/tss-lib/crypto/modproof/negative_test.go @@ -0,0 +1,80 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package modproof + +import ( + "math/big" + "testing" +) + +func TestValidateBasicNilW(t *testing.T) { + pf := &ProofMod{W: nil} + if pf.ValidateBasic() { + t.Fatal("nil W should fail") + } +} + +func TestValidateBasicNilXElement(t *testing.T) { + pf := &ProofMod{ + W: big.NewInt(1), + A: big.NewInt(1), + B: big.NewInt(1), + } + pf.X[0] = nil + if pf.ValidateBasic() { + t.Fatal("nil X[0] should fail") + } +} + +func TestValidateBasicNilA(t *testing.T) { + pf := &ProofMod{W: big.NewInt(1), A: nil} + for i := range pf.X { + pf.X[i] = big.NewInt(1) + } + if pf.ValidateBasic() { + t.Fatal("nil A should fail") + } +} + +func TestValidateBasicNilB(t *testing.T) { + pf := &ProofMod{W: big.NewInt(1), A: big.NewInt(1), B: nil} + for i := range pf.X { + pf.X[i] = big.NewInt(1) + } + if pf.ValidateBasic() { + t.Fatal("nil B should fail") + } +} + +func TestValidateBasicNilZElement(t *testing.T) { + pf := &ProofMod{W: big.NewInt(1), A: big.NewInt(1), B: big.NewInt(1)} + for i := range pf.X { + pf.X[i] = big.NewInt(1) + } + pf.Z[0] = nil + if pf.ValidateBasic() { + t.Fatal("nil Z[0] should fail") + } +} + +func TestValidateBasicAllValid(t *testing.T) { + pf := &ProofMod{W: big.NewInt(1), A: big.NewInt(1), B: big.NewInt(1)} + for i := range pf.X { + pf.X[i] = big.NewInt(1) + } + for i := range pf.Z { + pf.Z[i] = big.NewInt(1) + } + if !pf.ValidateBasic() { + t.Fatal("all-valid should pass") + } +} + +func TestNewProofFromBytesTruncated(t *testing.T) { + _, err := NewProofFromBytes([][]byte{{1}}) + if err == nil { + t.Fatal("expected error for truncated bytes") + } +} diff --git a/tss-lib/crypto/modproof/proof.go b/tss-lib/crypto/modproof/proof.go index f6aae03..e325766 100644 --- a/tss-lib/crypto/modproof/proof.go +++ b/tss-lib/crypto/modproof/proof.go @@ -1,17 +1,17 @@ -// Copyright © 2019-2023 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019-2023 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package modproof import ( + "errors" "fmt" "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) const ( @@ -36,6 +36,7 @@ func isQuadraticResidue(X, N *big.Int) bool { return big.Jacobi(X, N) == 1 } +// NewProof generates a mod proof. Session provides SSID domain separation. func NewProof(Session []byte, N, P, Q *big.Int, rand io.Reader) (*ProofMod, error) { Phi := new(big.Int).Mul(new(big.Int).Sub(P, one), new(big.Int).Sub(Q, one)) // Fig 16.1 @@ -51,6 +52,9 @@ func NewProof(Session []byte, N, P, Q *big.Int, rand io.Reader) (*ProofMod, erro // Fig 16.3 modN, modPhi := common.ModInt(N), common.ModInt(Phi) invN := new(big.Int).ModInverse(N, Phi) + if invN == nil { + return nil, errors.New("n not coprime with phi") + } X := [Iterations]*big.Int{} // Fix bitLen of A and B A := new(big.Int).Lsh(one, Iterations) @@ -81,6 +85,24 @@ func NewProof(Session []byte, N, P, Q *big.Int, rand io.Reader) (*ProofMod, erro break } } + // [FORK] Defense-in-depth: fail fast if no quadratic residue was found. + // + // This condition is unreachable when P and Q are safe primes because: + // - Safe primes satisfy P ≡ Q ≡ 3 (mod 4), so Jacobi(-1, P) = Jacobi(-1, Q) = -1 + // (negation flips both Legendre symbols). + // - W has Jacobi(W, N) = -1, meaning it flips exactly one of the two + // Legendre symbols (QNR mod one prime, QR mod the other). + // - Together, the four candidates {Y, -Y, W·Y, -W·Y} cycle through all four + // quadratic residuosity classes (QR/QR, QR/NR, NR/QR, NR/NR), so exactly + // one candidate is always a QR mod both P and Q. + // + // If this error fires, it indicates P or Q are not safe primes (not ≡ 3 mod 4), + // or N is otherwise malformed. Without this check, NewProof would return a proof + // with nil X[i]/Z[i] entries that silently fails verification at a remote party, + // obscuring the root cause. + if X[i] == nil { + return nil, fmt.Errorf("NewProof: no quadratic residue found for Y[%d]; P and Q must be safe primes (≡ 3 mod 4)", i) + } } pf := &ProofMod{W: W, X: X, A: A, B: B, Z: Z} @@ -93,7 +115,7 @@ func NewProofFromBytes(bzs [][]byte) (*ProofMod, error) { } bis := make([]*big.Int, len(bzs)) for i := range bis { - bis[i] = new(big.Int).SetBytes(bzs[i]) + bis[i] = new(big.Int).SetBytes(bzs[i]) //nolint:gosec // i bounded by len(bzs) } X := [Iterations]*big.Int{} @@ -115,10 +137,15 @@ func (pf *ProofMod) Verify(Session []byte, N *big.Int) bool { if pf == nil || !pf.ValidateBasic() { return false } - // TODO: add basic properties checker + // [FORK] Reject N that is too small to be secure (must be at least 2048 bits). + // Upstream does not check N's size. + if N == nil || N.BitLen() < 2048 { + return false + } if isQuadraticResidue(pf.W, N) { return false } + // Validate W is in the correct range and coprime with N. if pf.W.Sign() != 1 || pf.W.Cmp(N) != -1 { return false } @@ -126,6 +153,8 @@ func (pf *ProofMod) Verify(Session []byte, N *big.Int) bool { if gcd.Cmp(one) != 0 { return false } + // Range checks on proof elements: Z[i] and X[i] must be in (1, N), + // and A/B must have the correct bit length. for i := range pf.Z { if pf.Z[i].Sign() != 1 || pf.Z[i].Cmp(N) != -1 { return false @@ -160,6 +189,11 @@ func (pf *ProofMod) Verify(Session []byte, N *big.Int) bool { chs := make(chan bool, Iterations*2) for i := 0; i < Iterations; i++ { go func(i int) { + defer func() { + if r := recover(); r != nil { + chs <- false + } + }() left := modN.Exp(pf.Z[i], N) if left.Cmp(Y[i]) != 0 { chs <- false @@ -169,8 +203,16 @@ func (pf *ProofMod) Verify(Session []byte, N *big.Int) bool { }(i) go func(i int) { + defer func() { + if r := recover(); r != nil { + chs <- false + } + }() a := pf.A.Bit(i) b := pf.B.Bit(i) + // Defense-in-depth: Bit() always returns 0 or 1 per Go stdlib (math/big), + // so these conditions are unreachable. Retained as a safeguard against + // hypothetical stdlib behavior changes. if a != 0 && a != 1 { chs <- false return diff --git a/tss-lib/crypto/modproof/proof_test.go b/tss-lib/crypto/modproof/proof_test.go index afeac7f..299fd69 100644 --- a/tss-lib/crypto/modproof/proof_test.go +++ b/tss-lib/crypto/modproof/proof_test.go @@ -1,8 +1,7 @@ -// Copyright © 2019-2023 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019-2023 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package modproof_test @@ -11,36 +10,38 @@ import ( "fmt" "math/big" "testing" - "time" - "github.com/hemilabs/x/tss-lib/v2/common" - . "github.com/hemilabs/x/tss-lib/v2/crypto/modproof" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/stretchr/testify/assert" + "github.com/hemilabs/x/tss-lib/v3/common" + . "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/testutil" ) var Session = []byte("session") func TestMod(test *testing.T) { - preParams, err := keygen.GeneratePreParams(time.Minute*10, 8) - assert.NoError(test, err) + pps := testutil.LoadPreParams(test, 1) + preParams := &pps[0] P, Q, N := preParams.PaillierSK.P, preParams.PaillierSK.Q, preParams.PaillierSK.N proof, err := NewProof(Session, N, P, Q, rand.Reader) - assert.NoError(test, err) + if err != nil { + test.Fatal(err) + } proofBzs := proof.Bytes() proof, err = NewProofFromBytes(proofBzs[:]) - assert.NoError(test, err) + if err != nil { + test.Fatal(err) + } ok := proof.Verify(Session, N) - assert.True(test, ok, "proof must verify") + if !ok { + test.Fatal("proof must verify") + } } -var ( - one = big.NewInt(1) -) +var one = big.NewInt(1) func NewHackedProof(Session []byte, N, P *big.Int, Q []*big.Int) (*ProofMod, error) { Phi := new(big.Int).Sub(P, one) @@ -106,6 +107,51 @@ func mustSetString(s string) *big.Int { return i } +func TestModProofRejectsSmallN(test *testing.T) { + // Generate valid 2048-bit parameters and a valid proof. + pps := testutil.LoadPreParams(test, 1) + preParams := &pps[0] + + P, Q, N := preParams.PaillierSK.P, preParams.PaillierSK.Q, preParams.PaillierSK.N + + proof, err := NewProof(Session, N, P, Q, rand.Reader) + if err != nil { + test.Fatal(err) + } + + // Sanity: the proof must pass with the proper N (>= 2048 bits). + ok := proof.Verify(Session, N) + if !ok { + test.Fatal("proof must verify with proper 2048-bit N") + } + + // Build a small N (1024-bit) from two 512-bit primes. + smallP, err := rand.Prime(rand.Reader, 512) + if err != nil { + test.Fatal(err) + } + smallQ, err := rand.Prime(rand.Reader, 512) + if err != nil { + test.Fatal(err) + } + smallN := new(big.Int).Mul(smallP, smallQ) + if !(smallN.BitLen() < 2048) { + test.Fatal("smallN must be less than 2048 bits") + } + + // The [FORK] BitLen < 2048 check in Verify must reject smallN. + ok = proof.Verify(Session, smallN) + if ok { + test.Fatal("proof must be rejected when N.BitLen() < 2048") + } + + // nil N must also be rejected. + ok = proof.Verify(Session, nil) + if ok { + test.Fatal("proof must be rejected when N is nil") + } +} + func TestAttackMod(test *testing.T) { fmt.Printf("Starting TestAttackMod\n") @@ -129,7 +175,11 @@ func TestAttackMod(test *testing.T) { N.Mul(N, q) } proof, err := NewHackedProof(Session, N, P, Q) - assert.NoError(test, err) + if err != nil { + test.Fatal(err) + } ok := proof.Verify(Session, N) - assert.Falsef(test, ok, "false proof should not verify") + if ok { + test.Fatalf("false proof should not verify") + } } diff --git a/tss-lib/crypto/mta/mta_test.go b/tss-lib/crypto/mta/mta_test.go new file mode 100644 index 0000000..a353e4c --- /dev/null +++ b/tss-lib/crypto/mta/mta_test.go @@ -0,0 +1,1125 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package mta_test + +import ( + "context" + "crypto/rand" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +const testPaillierKeyLength = 2048 + +// testSafePrimeBits uses smaller primes for test speed. +const testSafePrimeBits = 1024 + +var testSession = []byte("test-mta-session") + +// testSetup generates the two Paillier keypairs + DLN parameters +// needed by the MtA protocol. Slow (~5s) due to safe prime gen. +type testParams struct { + ec func() *big.Int // returns curve order + pkA, pkB *paillier.PublicKey + skA, skB *paillier.PrivateKey + NTildeA, h1A, h2A *big.Int + NTildeB, h1B, h2B *big.Int +} + +func setup(t *testing.T) *testParams { + t.Helper() + ec := tss.S256() + + skA, pkA, err := paillier.GenerateKeyPair(context.Background(), + rand.Reader, testSafePrimeBits*2) + if err != nil { + t.Fatalf("GenerateKeyPair(A): %v", err) + } + skB, pkB, err := paillier.GenerateKeyPair(context.Background(), + rand.Reader, testSafePrimeBits*2) + if err != nil { + t.Fatalf("GenerateKeyPair(B): %v", err) + } + + primesA := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NTildeA, h1A, h2A, err := crypto.GenerateNTildei(rand.Reader, primesA) + if err != nil { + t.Fatalf("GenerateNTildei(A): %v", err) + } + + primesB := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NTildeB, h1B, h2B, err := crypto.GenerateNTildei(rand.Reader, primesB) + if err != nil { + t.Fatalf("GenerateNTildei(B): %v", err) + } + + return &testParams{ + ec: func() *big.Int { return ec.Params().N }, + pkA: pkA, skA: skA, + pkB: pkB, skB: skB, + NTildeA: NTildeA, h1A: h1A, h2A: h2A, + NTildeB: NTildeB, h1B: h1B, h2B: h2B, + } +} + +// TestMtAFullProtocol runs the complete Alice→Bob→Alice MtA without +// witness check: AliceInit → BobMid → AliceEnd. +func TestMtAFullProtocol(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + a := common.GetRandomPositiveInt(rand.Reader, q) + b := common.GetRandomPositiveInt(rand.Reader, q) + + aliceSession := append(testSession, byte(0)) + bobSession := append(testSession, byte(1)) + + // Alice step 1: encrypt a, produce range proof + cA, pfA, err := mta.AliceInit(aliceSession, ec, p.pkA, a, + p.NTildeB, p.h1B, p.h2B, rand.Reader) + if err != nil { + t.Fatalf("AliceInit: %v", err) + } + if cA == nil || pfA == nil { + t.Fatal("AliceInit returned nil") + } + + // Bob step: multiply cA by b, add blinding, produce Bob proof + beta, cB, betaPrm, piB, err := mta.BobMid(aliceSession, bobSession, + ec, p.pkA, pfA, b, cA, + p.NTildeA, p.h1A, p.h2A, + p.NTildeB, p.h1B, p.h2B, rand.Reader) + if err != nil { + t.Fatalf("BobMid: %v", err) + } + if beta == nil || cB == nil || betaPrm == nil || piB == nil { + t.Fatal("BobMid returned nil") + } + + // Alice step 2: decrypt cB to get alpha + alpha, err := mta.AliceEnd(bobSession, ec, p.pkA, piB, + p.h1A, p.h2A, cA, cB, p.NTildeA, p.skA) + if err != nil { + t.Fatalf("AliceEnd: %v", err) + } + + // Verify: alpha + beta ≡ a*b (mod q) + sum := new(big.Int).Add(alpha, beta) + sum.Mod(sum, q) + product := new(big.Int).Mul(a, b) + product.Mod(product, q) + if sum.Cmp(product) != 0 { + t.Fatalf("MtA failed: alpha+beta != a*b mod q\n sum=%x\n product=%x", sum, product) + } + t.Logf("MtA OK: alpha+beta ≡ a*b (mod q)") +} + +// TestMtAWithWitnessCheck runs AliceInit → BobMidWC → AliceEndWC. +func TestMtAWithWitnessCheck(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + a := common.GetRandomPositiveInt(rand.Reader, q) + b := common.GetRandomPositiveInt(rand.Reader, q) + B := crypto.ScalarBaseMult(ec, b) // witness: b*G + + aliceSession := append(testSession, byte(0)) + bobSession := append(testSession, byte(1)) + + cA, pfA, err := mta.AliceInit(aliceSession, ec, p.pkA, a, + p.NTildeB, p.h1B, p.h2B, rand.Reader) + if err != nil { + t.Fatalf("AliceInit: %v", err) + } + + beta, cB, betaPrm, piB, err := mta.BobMidWC(aliceSession, bobSession, + ec, p.pkA, pfA, b, cA, + p.NTildeA, p.h1A, p.h2A, + p.NTildeB, p.h1B, p.h2B, + B, rand.Reader) + if err != nil { + t.Fatalf("BobMidWC: %v", err) + } + if beta == nil || cB == nil || betaPrm == nil || piB == nil { + t.Fatal("BobMidWC returned nil") + } + + alpha, err := mta.AliceEndWC(bobSession, ec, p.pkA, piB, B, + cA, cB, p.NTildeA, p.h1A, p.h2A, p.skA) + if err != nil { + t.Fatalf("AliceEndWC: %v", err) + } + + sum := new(big.Int).Add(alpha, beta) + sum.Mod(sum, q) + product := new(big.Int).Mul(a, b) + product.Mod(product, q) + if sum.Cmp(product) != 0 { + t.Fatalf("MtA(WC) failed: alpha+beta != a*b mod q") + } + t.Logf("MtA(WC) OK: alpha+beta ≡ a*b (mod q)") +} + +// TestRangeProofAliceRoundTrip tests create → verify → bytes → from bytes. +func TestRangeProofAliceRoundTrip(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + pf, err := mta.ProveRangeAlice(testSession, ec, p.pkA, c, + p.NTildeB, p.h1B, p.h2B, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + if !pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("RangeProofAlice verify failed") + } + if !pf.ValidateBasic() { + t.Fatal("ValidateBasic failed") + } + + // Bytes round-trip + bzs := pf.Bytes() + pf2, err := mta.RangeProofAliceFromBytes(bzs[:]) + if err != nil { + t.Fatalf("FromBytes: %v", err) + } + if !pf2.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("RangeProofAlice verify after round-trip failed") + } + t.Log("RangeProofAlice round-trip OK") +} + +// TestProofBobRoundTrip tests create → verify → bytes → from bytes. +func TestProofBobRoundTrip(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + // c2 = cA^b * Enc(beta') homomorphically + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + // c2 = cA^b * cBeta mod N^2 + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("ProofBob verify failed") + } + if !pf.ValidateBasic() { + t.Fatal("ValidateBasic failed") + } + + bzs := pf.Bytes() + pf2, err := mta.ProofBobFromBytes(bzs[:]) + if err != nil { + t.Fatalf("FromBytes: %v", err) + } + if !pf2.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("ProofBob verify after round-trip failed") + } + t.Log("ProofBob round-trip OK") +} + +// TestAliceInitNilArgs verifies nil argument rejection. +func TestAliceInitNilArgs(t *testing.T) { + ec := tss.S256() + _, _, err := mta.AliceInit(testSession, ec, nil, big.NewInt(1), + big.NewInt(1), big.NewInt(1), big.NewInt(1), rand.Reader) + if err == nil { + t.Fatal("expected error for nil pkA") + } +} + +// TestProofBobWCRoundTrip tests create → verify → bytes → from bytes for WC variant. +func TestProofBobWCRoundTrip(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + B := crypto.ScalarBaseMult(ec, b) // witness + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBobWC(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, B, rand.Reader) + if err != nil { + t.Fatalf("ProveBobWC: %v", err) + } + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2, B) { + t.Fatal("ProofBobWC verify failed") + } + if !pf.ValidateBasic() { + t.Fatal("ValidateBasic failed") + } + + // Bytes round-trip + bzs := pf.Bytes() + pf2, err := mta.ProofBobWCFromBytes(ec, bzs[:]) + if err != nil { + t.Fatalf("ProofBobWCFromBytes: %v", err) + } + if !pf2.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2, B) { + t.Fatal("ProofBobWC verify after round-trip failed") + } + if !pf2.ValidateBasic() { + t.Fatal("ValidateBasic after round-trip failed") + } + t.Log("ProofBobWC round-trip OK") +} + +// TestRangeProofAliceRejectsWrongSession verifies that a RangeProofAlice +// generated with one session tag is rejected when verified with a different +// session tag. This is critical for domain separation: proofs from one +// ceremony must not be replayable in another. +func TestRangeProofAliceRejectsWrongSession(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + pf, err := mta.ProveRangeAlice(testSession, ec, p.pkA, c, + p.NTildeB, p.h1B, p.h2B, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + + // Sanity: honest proof verifies with the original session. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("honest proof must verify with correct session") + } + + // Cross-session: proof must be rejected with a different session tag. + wrongSession := []byte("wrong-session") + if pf.Verify(wrongSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("RangeProofAlice must be rejected with wrong session") + } + t.Log("RangeProofAlice correctly rejected with wrong session") +} + +// TestProofBobRejectsWrongSession verifies that a ProofBob generated with one +// session tag is rejected when verified with a different session tag. This is +// critical for domain separation: proofs from one ceremony must not be +// replayable in another. +func TestProofBobRejectsWrongSession(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + // c2 = cA^b * Enc(beta') homomorphically + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + // Sanity: honest proof verifies with the original session. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("honest proof must verify with correct session") + } + + // Cross-session: proof must be rejected with a different session tag. + wrongSession := []byte("wrong-session") + if pf.Verify(wrongSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("ProofBob must be rejected with wrong session") + } + t.Log("ProofBob correctly rejected with wrong session") +} + +// --------------------------------------------------------------------------- +// Category 1: Negative tests using external package (adversarial Verify params) +// --------------------------------------------------------------------------- + +// TestRangeProofAliceRejectsDegeneratePedersen verifies that the fork rejects +// RangeProofAlice when the verifier is given degenerate Pedersen parameters +// (h1=1 or h2=1), which eliminate binding or hiding respectively. +func TestRangeProofAliceRejectsDegeneratePedersen(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + pf, err := mta.ProveRangeAlice(testSession, ec, p.pkA, c, + p.NTildeB, p.h1B, p.h2B, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("honest proof must verify") + } + + // Degenerate h1=1. + if pf.Verify(testSession, ec, p.pkA, p.NTildeB, big.NewInt(1), p.h2B, c) { + t.Fatal("RangeProofAlice must be rejected with h1=1") + } + + // Degenerate h2=1. + if pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, big.NewInt(1), c) { + t.Fatal("RangeProofAlice must be rejected with h2=1") + } + t.Log("RangeProofAlice correctly rejected with degenerate Pedersen params") +} + +// TestProofBobRejectsDegeneratePedersen verifies that the fork rejects +// ProofBob when the verifier is given degenerate Pedersen parameters. +func TestProofBobRejectsDegeneratePedersen(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("honest proof must verify") + } + + // Degenerate h1=1. + if pf.Verify(testSession, ec, p.pkA, p.NTildeA, big.NewInt(1), p.h2A, cA, c2) { + t.Fatal("ProofBob must be rejected with h1=1") + } + + // Degenerate h2=1. + if pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, big.NewInt(1), cA, c2) { + t.Fatal("ProofBob must be rejected with h2=1") + } + t.Log("ProofBob correctly rejected with degenerate Pedersen params") +} + +// TestRangeProofAliceRejectsSmallNTilde verifies that the fork rejects +// RangeProofAlice when verified with a ~512-bit NTilde (below the 2048-bit minimum). +func TestRangeProofAliceRejectsSmallNTilde(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + pf, err := mta.ProveRangeAlice(testSession, ec, p.pkA, c, + p.NTildeB, p.h1B, p.h2B, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("honest proof must verify") + } + + // Small NTilde: product of two 256-bit primes (~512 bits). + p1 := common.GetRandomPrimeInt(rand.Reader, 256) + p2 := common.GetRandomPrimeInt(rand.Reader, 256) + smallNTilde := new(big.Int).Mul(p1, p2) + + if pf.Verify(testSession, ec, p.pkA, smallNTilde, p.h1B, p.h2B, c) { + t.Fatal("RangeProofAlice must be rejected with small NTilde") + } + t.Log("RangeProofAlice correctly rejected with small NTilde") +} + +// TestProofBobRejectsSmallNTilde verifies that the fork rejects ProofBob +// when verified with a ~512-bit NTilde. +func TestProofBobRejectsSmallNTilde(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("honest proof must verify") + } + + // Small NTilde: product of two 256-bit primes (~512 bits). + p1 := common.GetRandomPrimeInt(rand.Reader, 256) + p2 := common.GetRandomPrimeInt(rand.Reader, 256) + smallNTilde := new(big.Int).Mul(p1, p2) + + if pf.Verify(testSession, ec, p.pkA, smallNTilde, p.h1A, p.h2A, cA, c2) { + t.Fatal("ProofBob must be rejected with small NTilde") + } + t.Log("ProofBob correctly rejected with small NTilde") +} + +// TestRangeProofAliceRejectsNonCoprimeC verifies that the fork rejects +// RangeProofAlice when the ciphertext c shares a factor with N^2 +// (i.e., c = pkA.N). This would reveal N's factorization. +func TestRangeProofAliceRejectsNonCoprimeC(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + pf, err := mta.ProveRangeAlice(testSession, ec, p.pkA, c, + p.NTildeB, p.h1B, p.h2B, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("honest proof must verify") + } + + // Adversarial c = pkA.N (shares factor with N^2). + badC := new(big.Int).Set(p.pkA.N) + if pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, badC) { + t.Fatal("RangeProofAlice must be rejected when c shares factor with N") + } + t.Log("RangeProofAlice correctly rejected with non-coprime c") +} + +// TestProofBobRejectsNonCoprimeC1 verifies that the fork rejects ProofBob +// when c1 shares a factor with pkA.N. +func TestProofBobRejectsNonCoprimeC1(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("honest proof must verify") + } + + // Adversarial c1 = pkA.N. + badC1 := new(big.Int).Set(p.pkA.N) + if pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, badC1, c2) { + t.Fatal("ProofBob must be rejected when c1 shares factor with N") + } + t.Log("ProofBob correctly rejected with non-coprime c1") +} + +// TestProofBobRejectsNonCoprimeC2 verifies that the fork rejects ProofBob +// when c2 shares a factor with pkA.N. +func TestProofBobRejectsNonCoprimeC2(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("honest proof must verify") + } + + // Adversarial c2 = pkA.N. + badC2 := new(big.Int).Set(p.pkA.N) + if pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, badC2) { + t.Fatal("ProofBob must be rejected when c2 shares factor with N") + } + t.Log("ProofBob correctly rejected with non-coprime c2") +} + +// TestRangeProofAliceRejectsSmallPaillierN verifies that the fork rejects +// RangeProofAlice when verified with a small (512-bit) Paillier public key. +func TestRangeProofAliceRejectsSmallPaillierN(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + pf, err := mta.ProveRangeAlice(testSession, ec, p.pkA, c, + p.NTildeB, p.h1B, p.h2B, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("honest proof must verify") + } + + // Generate a small (512-bit) Paillier key. + _, smallPK, err := paillier.GenerateKeyPair(context.Background(), rand.Reader, 512) + if err != nil { + t.Fatalf("GenerateKeyPair(small): %v", err) + } + + if pf.Verify(testSession, ec, smallPK, p.NTildeB, p.h1B, p.h2B, c) { + t.Fatal("RangeProofAlice must be rejected with small Paillier N") + } + t.Log("RangeProofAlice correctly rejected with small Paillier N") +} + +// TestProofBobRejectsSmallPaillierN verifies that the fork rejects ProofBob +// when verified with a small (512-bit) Paillier public key. +func TestProofBobRejectsSmallPaillierN(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBob(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("honest proof must verify") + } + + // Generate a small (512-bit) Paillier key. + _, smallPK, err := paillier.GenerateKeyPair(context.Background(), rand.Reader, 512) + if err != nil { + t.Fatalf("GenerateKeyPair(small): %v", err) + } + + if pf.Verify(testSession, ec, smallPK, p.NTildeA, p.h1A, p.h2A, cA, c2) { + t.Fatal("ProofBob must be rejected with small Paillier N") + } + t.Log("ProofBob correctly rejected with small Paillier N") +} + +// --------------------------------------------------------------------------- +// B32: ProofBobWC rejects s1ModQ == 0 (proofs.go:361) +// --------------------------------------------------------------------------- + +// TestProofBobWCRejectsS1ModQZero verifies that the fork's s1ModQ=0 guard +// (proofs.go:361) rejects a ProofBobWC whose S1 is set to the curve order q. +// When S1 = q, s1ModQ = q mod q = 0 and the EC scalar multiply would produce +// the identity point, so the check fires first. +func TestProofBobWCRejectsS1ModQZero(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + B := crypto.ScalarBaseMult(ec, b) // witness: b*G + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBobWC(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, B, rand.Reader) + if err != nil { + t.Fatalf("ProveBobWC: %v", err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2, B) { + t.Fatal("honest ProofBobWC must verify") + } + + // Tamper: set S1 = q so that s1ModQ = q mod q = 0. + pf.S1 = new(big.Int).Set(q) + if pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2, B) { + t.Fatal("ProofBobWC must be rejected when S1 = q (s1ModQ = 0)") + } + t.Log("ProofBobWC correctly rejected with S1 = q (B32: s1ModQ == 0)") +} + +// --------------------------------------------------------------------------- +// B33: ProofBobWC e == 0 guard (proofs.go:364) +// --------------------------------------------------------------------------- + +// TestProofBobWCRejectsEZero documents that the e=0 guard at proofs.go:364 +// exists as defense-in-depth. The challenge e is computed as +// RejectionSample(q, SHA512_256i_TAGGED(Session, ...)), which outputs 0 only +// if the hash maps to 0 mod q -- computationally infeasible (requires a +// 256-bit hash preimage). We cannot trigger this via external inputs, so +// this test documents the check and verifies the surrounding code path. +func TestProofBobWCRejectsEZero(t *testing.T) { + p := setup(t) + ec := tss.S256() + q := ec.Params().N + + b := common.GetRandomPositiveInt(rand.Reader, q) + a := common.GetRandomPositiveInt(rand.Reader, q) + B := crypto.ScalarBaseMult(ec, b) + + cA, _, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + beta := common.GetRandomPositiveInt(rand.Reader, q) + cBeta, rBeta, err := p.pkA.EncryptAndReturnRandomness(rand.Reader, beta) + if err != nil { + t.Fatalf("Encrypt(beta): %v", err) + } + N2 := new(big.Int).Mul(p.pkA.N, p.pkA.N) + c2 := new(big.Int).Exp(cA, b, N2) + c2.Mul(c2, cBeta) + c2.Mod(c2, N2) + + pf, err := mta.ProveBobWC(testSession, ec, p.pkA, + p.NTildeA, p.h1A, p.h2A, cA, c2, b, beta, rBeta, B, rand.Reader) + if err != nil { + t.Fatalf("ProveBobWC: %v", err) + } + + // Sanity: honest proof verifies (the e=0 path is not hit). + if !pf.Verify(testSession, ec, p.pkA, p.NTildeA, p.h1A, p.h2A, cA, c2, B) { + t.Fatal("honest ProofBobWC must verify") + } + t.Log("ProofBobWC sanity verified (B33: e=0 guard is defense-in-depth, computationally infeasible to trigger)") + + // B33: e=0 requires SHA512_256i_TAGGED to produce 0 mod q, which is a + // hash preimage problem. Cannot be triggered via external inputs. + t.Skip("B33: e=0 requires hash preimage, computationally infeasible to trigger externally") +} + +// --------------------------------------------------------------------------- +// Category 2: Negative tests (proof field mutation) — migrated from internal +// --------------------------------------------------------------------------- + +// aliceProofFixture creates an honest RangeProofAlice with fresh Paillier keys +// and Pedersen parameters. Returns the proof and all public verification inputs. +func aliceProofFixture(t *testing.T) (*mta.RangeProofAlice, *paillier.PublicKey, *big.Int, *big.Int, *big.Int, *big.Int) { + t.Helper() + ec := tss.S256() + q := ec.Params().N + + _, pk, err := paillier.GenerateKeyPair(context.Background(), rand.Reader, testPaillierKeyLength) + if err != nil { + t.Fatalf("GenerateKeyPair: %v", err) + } + + m := common.GetRandomPositiveInt(rand.Reader, q) + c, r, err := pk.EncryptAndReturnRandomness(rand.Reader, m) + if err != nil { + t.Fatalf("Encrypt: %v", err) + } + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NTilde, h1, h2, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + t.Fatalf("GenerateNTildei: %v", err) + } + + proof, err := mta.ProveRangeAlice(testSession, ec, pk, c, NTilde, h1, h2, m, r, rand.Reader) + if err != nil { + t.Fatalf("ProveRangeAlice: %v", err) + } + + return proof, pk, NTilde, h1, h2, c +} + +// bobProofFixture creates an honest ProofBob with fresh Paillier keys and +// Pedersen parameters. Returns the proof and all public verification inputs. +func bobProofFixture(t *testing.T) (*mta.ProofBob, *paillier.PublicKey, *big.Int, *big.Int, *big.Int, *big.Int, *big.Int) { + t.Helper() + ec := tss.S256() + q := ec.Params().N + + _, pk, err := paillier.GenerateKeyPair(context.Background(), rand.Reader, testPaillierKeyLength) + if err != nil { + t.Fatalf("GenerateKeyPair: %v", err) + } + + // Alice's ciphertext c1 = Enc(a). + a := common.GetRandomPositiveInt(rand.Reader, q) + c1, _, err := pk.EncryptAndReturnRandomness(rand.Reader, a) + if err != nil { + t.Fatalf("Encrypt(a): %v", err) + } + + // Bob's secrets: b (multiplier), betaPrm (additive share). + b := common.GetRandomPositiveInt(rand.Reader, q) + betaPrm := common.GetRandomPositiveInt(rand.Reader, q) + + // Bob computes c2 = c1^b * Enc(betaPrm, cRand) mod N^2. + cBTimesA, err := pk.HomoMult(b, c1) + if err != nil { + t.Fatalf("HomoMult: %v", err) + } + cBetaPrm, cRand, err := pk.EncryptAndReturnRandomness(rand.Reader, betaPrm) + if err != nil { + t.Fatalf("Encrypt(betaPrm): %v", err) + } + c2, err := pk.HomoAdd(cBTimesA, cBetaPrm) + if err != nil { + t.Fatalf("HomoAdd: %v", err) + } + + primes := [2]*big.Int{ + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), + } + NTilde, h1, h2, err := crypto.GenerateNTildei(rand.Reader, primes) + if err != nil { + t.Fatalf("GenerateNTildei: %v", err) + } + + proof, err := mta.ProveBob(testSession, ec, pk, NTilde, h1, h2, c1, c2, b, betaPrm, cRand, rand.Reader) + if err != nil { + t.Fatalf("ProveBob: %v", err) + } + + return proof, pk, NTilde, h1, h2, c1, c2 +} + +// TestRangeProofAliceRejectsOversizedS2 verifies that the fork's S2 upper +// bound check (S2 <= 2*q^3*NTilde) rejects a tampered proof with S2 just +// above the bound. +func TestRangeProofAliceRejectsOversizedS2(t *testing.T) { + pf, pk, NTilde, h1, h2, c := aliceProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c) { + t.Fatal("honest proof must verify") + } + + // Compute the S2 upper bound: 2 * q^3 * NTilde. + q := ec.Params().N + q3 := new(big.Int).Mul(q, new(big.Int).Mul(q, q)) + s2Bound := new(big.Int).Lsh(new(big.Int).Mul(q3, NTilde), 1) + + // Tamper: set S2 = s2Bound + 1 (just over the limit). + pf.S2 = new(big.Int).Add(s2Bound, big.NewInt(1)) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c) { + t.Fatal("proof with oversized S2 must be rejected") + } + t.Log("RangeProofAlice correctly rejected with oversized S2") +} + +// TestProofBobRejectsOversizedS2 verifies that the fork's S2 upper bound +// check rejects a tampered ProofBob with S2 just above the bound. +func TestProofBobRejectsOversizedS2(t *testing.T) { + pf, pk, NTilde, h1, h2, c1, c2 := bobProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("honest proof must verify") + } + + // Compute the S2/T2 upper bound: 2 * q^3 * NTilde. + q := ec.Params().N + q3 := new(big.Int).Mul(q, new(big.Int).Mul(q, q)) + s2t2Bound := new(big.Int).Lsh(new(big.Int).Mul(q3, NTilde), 1) + + // Tamper: set S2 = s2t2Bound + 1. + pf.S2 = new(big.Int).Add(s2t2Bound, big.NewInt(1)) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("proof with oversized S2 must be rejected") + } + t.Log("ProofBob correctly rejected with oversized S2") +} + +// TestProofBobRejectsOversizedT2 verifies that the fork's T2 upper bound +// check rejects a tampered ProofBob with T2 just above the bound. +func TestProofBobRejectsOversizedT2(t *testing.T) { + pf, pk, NTilde, h1, h2, c1, c2 := bobProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("honest proof must verify") + } + + // Compute the S2/T2 upper bound: 2 * q^3 * NTilde. + q := ec.Params().N + q3 := new(big.Int).Mul(q, new(big.Int).Mul(q, q)) + s2t2Bound := new(big.Int).Lsh(new(big.Int).Mul(q3, NTilde), 1) + + // Tamper: set T2 = s2t2Bound + 1. + pf.T2 = new(big.Int).Add(s2t2Bound, big.NewInt(1)) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("proof with oversized T2 must be rejected") + } + t.Log("ProofBob correctly rejected with oversized T2") +} + +// TestProofBobRejectsZeroS verifies that the fork rejects a ProofBob +// when S is set to zero (degenerate element). +func TestProofBobRejectsZeroS(t *testing.T) { + pf, pk, NTilde, h1, h2, c1, c2 := bobProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("honest proof must verify") + } + + // Tamper: set S = 0. + pf.S = big.NewInt(0) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("proof with S=0 must be rejected") + } + t.Log("ProofBob correctly rejected with S=0") +} + +// TestProofBobRejectsZeroV verifies that the fork rejects a ProofBob +// when V is set to zero (degenerate element). +func TestProofBobRejectsZeroV(t *testing.T) { + pf, pk, NTilde, h1, h2, c1, c2 := bobProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("honest proof must verify") + } + + // Tamper: set V = 0. + pf.V = big.NewInt(0) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("proof with V=0 must be rejected") + } + t.Log("ProofBob correctly rejected with V=0") +} + +// TestProofBobRejectsNonCoprimeS verifies that the fork rejects a ProofBob +// when S shares a factor with pkA.N (GCD(S, N) != 1). +func TestProofBobRejectsNonCoprimeS(t *testing.T) { + pf, pk, NTilde, h1, h2, c1, c2 := bobProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("honest proof must verify") + } + + // Tamper: set S = pk.N (shares a factor with N, so GCD(S, N) = N != 1). + pf.S = new(big.Int).Set(pk.N) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("proof with S sharing factor with N must be rejected") + } + t.Log("ProofBob correctly rejected with non-coprime S") +} + +// TestProofBobRejectsNonCoprimeV verifies that the fork rejects a ProofBob +// when V shares a factor with pkA.N (GCD(V, N) != 1). +func TestProofBobRejectsNonCoprimeV(t *testing.T) { + pf, pk, NTilde, h1, h2, c1, c2 := bobProofFixture(t) + ec := tss.S256() + + // Sanity: honest proof verifies. + if !pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("honest proof must verify") + } + + // Tamper: set V = pk.N (shares a factor with N, so GCD(V, N) = N != 1). + pf.V = new(big.Int).Set(pk.N) + if pf.Verify(testSession, ec, pk, NTilde, h1, h2, c1, c2) { + t.Fatal("proof with V sharing factor with N must be rejected") + } + t.Log("ProofBob correctly rejected with non-coprime V") +} diff --git a/tss-lib/crypto/mta/proofs.go b/tss-lib/crypto/mta/proofs.go index fde9a11..2945873 100644 --- a/tss-lib/crypto/mta/proofs.go +++ b/tss-lib/crypto/mta/proofs.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package mta @@ -13,10 +12,10 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" ) const ( @@ -24,6 +23,8 @@ const ( ProofBobWCBytesParts = 12 ) +var zero = big.NewInt(0) + type ( ProofBob struct { Z, ZPrm, T, V, W, S, S1, S2, T1, T2 *big.Int @@ -37,6 +38,7 @@ type ( // ProveBobWC implements Bob's proof both with or without check "ProveMtawc_Bob" and "ProveMta_Bob" used in the MtA protocol from GG18Spec (9) Figs. 10 & 11. // an absent `X` generates the proof without the X consistency check X = g^x +// ProveBobWC implements Bob's proof. Session provides SSID domain separation (replay prevention). func ProveBobWC(Session []byte, ec elliptic.Curve, pk *paillier.PublicKey, NTilde, h1, h2, c1, c2, x, y, r *big.Int, X *crypto.ECPoint, rand io.Reader) (*ProofBobWC, error) { if pk == nil || NTilde == nil || h1 == nil || h2 == nil || c1 == nil || c2 == nil || x == nil || y == nil || r == nil { return nil, errors.New("ProveBob() received a nil argument") @@ -191,9 +193,44 @@ func ProofBobFromBytes(bzs [][]byte) (*ProofBob, error) { // ProveBobWC.Verify implements verification of Bob's proof with check "VerifyMtawc_Bob" used in the MtA protocol from GG18Spec (9) Fig. 10. // an absent `X` verifies a proof generated without the X consistency check X = g^x func (pf *ProofBobWC) Verify(Session []byte, ec elliptic.Curve, pk *paillier.PublicKey, NTilde, h1, h2, c1, c2 *big.Int, X *crypto.ECPoint) bool { + if pf == nil || pf.ProofBob == nil { + return false + } if pk == nil || NTilde == nil || h1 == nil || h2 == nil || c1 == nil || c2 == nil { return false } + // [FORK] Reject degenerate Pedersen parameters: h1=1 or h2=1 eliminates + // binding or hiding, making the range proof unsound. Upstream does not check. + one := big.NewInt(1) + if h1.Cmp(one) == 0 || h2.Cmp(one) == 0 { + return false + } + + // [FORK] Ciphertexts c1, c2 must be coprime to N (i.e. valid Paillier ciphertexts). + // A malicious ciphertext sharing a factor with N reveals N's factorization. + // Upstream does not check. + if new(big.Int).GCD(nil, nil, c1, pk.N).Cmp(one) != 0 { + return false + } + if new(big.Int).GCD(nil, nil, c2, pk.N).Cmp(one) != 0 { + return false + } + + // [FORK] NTilde (Pedersen commitment modulus) must be sufficiently large for soundness. + // Upstream does not check NTilde size in the proof verifier (only at keygen round 2). + // Defense-in-depth: proof verifiers should be self-contained against untrusted parameters. + if NTilde.BitLen() < 2048 { + return false + } + + // [FORK] Paillier modulus must also be sufficiently large. Upstream does not check + // pk.N size in the proof verifier. A malicious party could use a small Paillier key + // to break range proof soundness, allowing extraction of the discrete log from the + // ciphertext. Defense-in-depth: keygen round 2 validates exact 2048 bits, but the + // proof verifier should not rely on that. + if pk.N.BitLen() < 2048 { + return false + } q := ec.Params().N q3 := new(big.Int).Mul(q, q) // q^2 @@ -201,6 +238,9 @@ func (pf *ProofBobWC) Verify(Session []byte, ec elliptic.Curve, pk *paillier.Pub q7 := new(big.Int).Mul(q3, q3) // q^6 q7 = new(big.Int).Mul(q7, q) // q^7 + // Interval and coprimality checks on proof elements (present in both upstream and fork). + // Without them, a malicious prover can submit out-of-range or degenerate elements + // that cause modular arithmetic failures or weaken proof soundness. if !common.IsInInterval(pf.Z, NTilde) { return false } @@ -236,12 +276,17 @@ func (pf *ProofBobWC) Verify(Session []byte, ec elliptic.Curve, pk *paillier.Pub } gcd := big.NewInt(0) + // Defense-in-depth: S==0 is caught by the GCD check below (GCD(0,N)=N!=1), + // but an explicit zero-check makes the rejection reason unambiguous. if pf.S.Cmp(zero) == 0 { return false } if gcd.GCD(nil, nil, pf.S, pk.N).Cmp(one) != 0 { return false } + // Defense-in-depth: V==0 is caught by GCD(V,N^2)==1 on line 267, and + // GCD(V,N)!=1 below is implied by GCD(V,N^2)==1. Both retained for + // explicit rejection at the Paillier-N boundary, not just N^2. if pf.V.Cmp(zero) == 0 { return false } @@ -268,6 +313,24 @@ func (pf *ProofBobWC) Verify(Session []byte, ec elliptic.Curve, pk *paillier.Pub if pf.T1.Cmp(q7) > 0 { return false } + // [FORK] Defense-in-depth: s2 and t2 upper bounds. + // s2 = e·rho + rhoPrm where e ∈ [0, q), rho ∈ [1, q·NTilde), rhoPrm ∈ [1, q³·NTilde). + // t2 = e·sigma + tau where e ∈ [0, q), sigma ∈ [1, q·NTilde), tau ∈ [1, q³·NTilde). + // Both have the same maximum honest value: + // (q-1)(q·NTilde - 1) + (q³·NTilde - 1) = q³·NTilde + q²·NTilde - q·NTilde - q + // < 2·q³·NTilde (since q² < q³ for q > 1). + // This bound has EXACTLY ZERO false-rejection probability for honest provers. + // Without it, a malicious prover could submit arbitrarily large s2/t2 values, + // forcing the verifier to compute h2^s2 and h2^t2 with unbounded exponents, + // enabling DoS via expensive modular exponentiation. Upstream does not check. + q3NTilde := new(big.Int).Mul(q3, NTilde) + s2t2Bound := new(big.Int).Lsh(q3NTilde, 1) // 2 · q³ · NTilde + if pf.S2.Cmp(s2t2Bound) > 0 { + return false + } + if pf.T2.Cmp(s2t2Bound) > 0 { + return false + } // 1-2. e' var e *big.Int @@ -290,6 +353,13 @@ func (pf *ProofBobWC) Verify(Session []byte, ec elliptic.Curve, pk *paillier.Pub // 4. runs only in the "with check" mode from Fig. 10 if X != nil { s1ModQ := new(big.Int).Mod(pf.S1, ec.Params().N) + // [FORK] Guard s1ModQ=0 and e=0 before EC operations to prevent identity-point panic. + if s1ModQ.Sign() == 0 { + return false + } + if e.Sign() == 0 { + return false + } gS1 := crypto.ScalarBaseMult(ec, s1ModQ) xEU, err := X.ScalarMult(e).Add(pf.U) if err != nil || !gS1.Equals(xEU) { diff --git a/tss-lib/crypto/mta/range_proof.go b/tss-lib/crypto/mta/range_proof.go index c98ea18..3de15ed 100644 --- a/tss-lib/crypto/mta/range_proof.go +++ b/tss-lib/crypto/mta/range_proof.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package mta @@ -13,27 +12,23 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" ) const ( RangeProofAliceBytesParts = 6 ) -var ( - zero = big.NewInt(0) - one = big.NewInt(1) -) - type ( RangeProofAlice struct { Z, U, W, S, S1, S2 *big.Int } ) +// [FORK] Session parameter added for SSID domain separation (prevents cross-ceremony replay). // ProveRangeAlice implements Alice's range proof used in the MtA and MtAwc protocols from GG18Spec (9) Fig. 9. -func ProveRangeAlice(ec elliptic.Curve, pk *paillier.PublicKey, c, NTilde, h1, h2, m, r *big.Int, rand io.Reader) (*RangeProofAlice, error) { +func ProveRangeAlice(Session []byte, ec elliptic.Curve, pk *paillier.PublicKey, c, NTilde, h1, h2, m, r *big.Int, rand io.Reader) (*RangeProofAlice, error) { if pk == nil || NTilde == nil || h1 == nil || h2 == nil || c == nil || m == nil || r == nil { return nil, errors.New("ProveRangeAlice constructor received nil value(s)") } @@ -72,7 +67,7 @@ func ProveRangeAlice(ec elliptic.Curve, pk *paillier.PublicKey, c, NTilde, h1, h // 8-9. e' var e *big.Int { // must use RejectionSample - eHash := common.SHA512_256i(append(pk.AsInts(), c, z, u, w)...) + eHash := common.SHA512_256i_TAGGED(Session, append(pk.AsInts(), c, z, u, w)...) e = common.RejectionSample(q, eHash) } @@ -105,15 +100,38 @@ func RangeProofAliceFromBytes(bzs [][]byte) (*RangeProofAlice, error) { }, nil } -func (pf *RangeProofAlice) Verify(ec elliptic.Curve, pk *paillier.PublicKey, NTilde, h1, h2, c *big.Int) bool { +func (pf *RangeProofAlice) Verify(Session []byte, ec elliptic.Curve, pk *paillier.PublicKey, NTilde, h1, h2, c *big.Int) bool { if pf == nil || !pf.ValidateBasic() || pk == nil || NTilde == nil || h1 == nil || h2 == nil || c == nil { return false } + // [FORK] Reject degenerate Pedersen parameters: h1=1 or h2=1 eliminates + // binding or hiding, making the range proof unsound. Upstream does not check. + one := big.NewInt(1) + if h1.Cmp(one) == 0 || h2.Cmp(one) == 0 { + return false + } + + // [FORK] NTilde (Pedersen commitment modulus) must be sufficiently large for soundness. + // Upstream does not check NTilde size in the proof verifier (only at keygen round 2). + // Defense-in-depth: proof verifiers should be self-contained against untrusted parameters. + if NTilde.BitLen() < 2048 { + return false + } + + // [FORK] Paillier modulus must also be sufficiently large. Upstream does not check + // pk.N size in the proof verifier. Defense-in-depth: keygen round 2 validates exact + // 2048 bits, but the proof verifier should not rely on that. + if pk.N.BitLen() < 2048 { + return false + } q := ec.Params().N q3 := new(big.Int).Mul(q, q) q3 = new(big.Int).Mul(q, q3) + // Interval, coprimality, and degeneracy checks on proof elements (present in both + // upstream and fork). Without them, a malicious prover can submit out-of-range or + // degenerate elements that cause modular arithmetic failures or weaken soundness. if !common.IsInInterval(pf.Z, NTilde) { return false } @@ -155,17 +173,40 @@ func (pf *RangeProofAlice) Verify(ec elliptic.Curve, pk *paillier.PublicKey, NTi if pf.S1.Cmp(q3) == 1 { return false } + // [FORK] Defense-in-depth: s2 upper bound. Honest s2 = e·rho + gamma where + // e ∈ [0, q), rho ∈ [1, q·NTilde), gamma ∈ [1, q³·NTilde). + // Maximum honest value: (q-1)(q·NTilde - 1) + (q³·NTilde - 1) + // = q²·NTilde - q·NTilde - q + 1 + q³·NTilde - 1 + // = q³·NTilde + q²·NTilde - q·NTilde - q + // < 2·q³·NTilde (since q² < q³ for q > 1). + // This bound has EXACTLY ZERO false-rejection probability for honest provers. + // Without it, a malicious prover could set s2 to an arbitrarily large value, + // increasing the exponent size in h2^s2 and enabling DoS via expensive modular + // exponentiation (~2817-bit exponents are the honest maximum on secp256k1). + // Upstream does not check. + q3NTilde := new(big.Int).Mul(q3, NTilde) + s2Bound := new(big.Int).Lsh(q3NTilde, 1) // 2 · q³ · NTilde + if pf.S2.Cmp(s2Bound) == 1 { + return false + } // 1-2. e' var e *big.Int { // must use RejectionSample - eHash := common.SHA512_256i(append(pk.AsInts(), c, pf.Z, pf.U, pf.W)...) + eHash := common.SHA512_256i_TAGGED(Session, append(pk.AsInts(), c, pf.Z, pf.U, pf.W)...) e = common.RejectionSample(q, eHash) } var products *big.Int // for the following conditionals minusE := new(big.Int).Sub(zero, e) + // [FORK] Defense-in-depth: verify c is coprime with N^2 before negative-exponent + // computation. A malicious c with gcd(c, N^2) != 1 would cause Exp to + // return nil (ModInverse fails), triggering a nil-pointer panic. Upstream does not check. + if new(big.Int).GCD(nil, nil, c, pk.NSquare()).Cmp(one) != 0 { + return false + } + { // 4. gamma^s_1 * s^N * c^-e modNSquared := common.ModInt(pk.NSquare()) diff --git a/tss-lib/crypto/mta/range_proof_test.go b/tss-lib/crypto/mta/range_proof_test.go deleted file mode 100644 index 4e3e370..0000000 --- a/tss-lib/crypto/mta/range_proof_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package mta - -import ( - "context" - "crypto/rand" - "fmt" - "math/big" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Using a modulus length of 2048 is recommended in the GG18 spec -const ( - testSafePrimeBits = 1024 -) - -func TestProveRangeAlice(t *testing.T) { - q := tss.EC().Params().N - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - sk, pk, err := paillier.GenerateKeyPair(ctx, rand.Reader, testPaillierKeyLength) - assert.NoError(t, err) - - m := common.GetRandomPositiveInt(rand.Reader, q) - c, r, err := sk.EncryptAndReturnRandomness(rand.Reader, m) - assert.NoError(t, err) - - primes := [2]*big.Int{common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits)} - NTildei, h1i, h2i, err := crypto.GenerateNTildei(rand.Reader, primes) - assert.NoError(t, err) - proof, err := ProveRangeAlice(tss.EC(), pk, c, NTildei, h1i, h2i, m, r, rand.Reader) - assert.NoError(t, err) - - ok := proof.Verify(tss.EC(), pk, NTildei, h1i, h2i, c) - assert.True(t, ok, "proof must verify") -} - -func TestProveRangeAliceBypassed(t *testing.T) { - q := tss.EC().Params().N - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - sk0, pk0, err := paillier.GenerateKeyPair(ctx, rand.Reader, testPaillierKeyLength) - assert.NoError(t, err) - - m0 := common.GetRandomPositiveInt(rand.Reader, q) - c0, r0, err := sk0.EncryptAndReturnRandomness(rand.Reader, m0) - assert.NoError(t, err) - - primes0 := [2]*big.Int{common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits)} - Ntildei0, h1i0, h2i0, err := crypto.GenerateNTildei(rand.Reader, primes0) - assert.NoError(t, err) - proof0, err := ProveRangeAlice(tss.EC(), pk0, c0, Ntildei0, h1i0, h2i0, m0, r0, rand.Reader) - assert.NoError(t, err) - - ok0 := proof0.Verify(tss.EC(), pk0, Ntildei0, h1i0, h2i0, c0) - assert.True(t, ok0, "proof must verify") - - // proof 2 - sk1, pk1, err := paillier.GenerateKeyPair(ctx, rand.Reader, testPaillierKeyLength) - assert.NoError(t, err) - - m1 := common.GetRandomPositiveInt(rand.Reader, q) - c1, r1, err := sk1.EncryptAndReturnRandomness(rand.Reader, m1) - assert.NoError(t, err) - - primes1 := [2]*big.Int{common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits), common.GetRandomPrimeInt(rand.Reader, testSafePrimeBits)} - Ntildei1, h1i1, h2i1, err := crypto.GenerateNTildei(rand.Reader, primes1) - assert.NoError(t, err) - proof1, err := ProveRangeAlice(tss.EC(), pk1, c1, Ntildei1, h1i1, h2i1, m1, r1, rand.Reader) - assert.NoError(t, err) - - ok1 := proof1.Verify(tss.EC(), pk1, Ntildei1, h1i1, h2i1, c1) - assert.True(t, ok1, "proof must verify") - - cross0 := proof0.Verify(tss.EC(), pk1, Ntildei1, h1i1, h2i1, c1) - assert.False(t, cross0, "proof must not verify") - - cross1 := proof1.Verify(tss.EC(), pk0, Ntildei0, h1i0, h2i0, c0) - assert.False(t, cross1, "proof must not verify") - - fmt.Println("Did verify proof 0 with data from 0?", ok0) - fmt.Println("Did verify proof 1 with data from 1?", ok1) - - fmt.Println("Did verify proof 0 with data from 1?", cross0) - fmt.Println("Did verify proof 1 with data from 0?", cross1) - - // new bypass - bypassedproofNew := &RangeProofAlice{ - S: big.NewInt(1), - S1: big.NewInt(0), - S2: big.NewInt(0), - Z: big.NewInt(1), - U: big.NewInt(1), - W: big.NewInt(1), - } - - cBogus := big.NewInt(1) - proofBogus, _ := ProveRangeAlice(tss.EC(), pk1, cBogus, Ntildei1, h1i1, h2i1, m1, r1, rand.Reader) - - ok2 := proofBogus.Verify(tss.EC(), pk1, Ntildei1, h1i1, h2i1, cBogus) - bypassresult3 := bypassedproofNew.Verify(tss.EC(), pk1, Ntildei1, h1i1, h2i1, cBogus) - - // c = 1 is not valid, even though we can find a range proof for it that passes! - // this also means that the homo mul and add needs to be checked with this! - fmt.Println("Did verify proof bogus with data from bogus?", ok2) - fmt.Println("Did we bypass proof 3?", bypassresult3) -} diff --git a/tss-lib/crypto/mta/share_protocol.go b/tss-lib/crypto/mta/share_protocol.go index 34559bb..16fea69 100644 --- a/tss-lib/crypto/mta/share_protocol.go +++ b/tss-lib/crypto/mta/share_protocol.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package mta @@ -12,34 +11,38 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" ) -func AliceInit( - ec elliptic.Curve, - pkA *paillier.PublicKey, - a, NTildeB, h1B, h2B *big.Int, - rand io.Reader, -) (cA *big.Int, pf *RangeProofAlice, err error) { +// [FORK] Session parameter added for SSID domain separation (prevents cross-ceremony replay). +// Upstream has no Session parameter; hashes are not ceremony-bound. +func AliceInit(Session []byte, ec elliptic.Curve, pkA *paillier.PublicKey, a, NTildeB, h1B, h2B *big.Int, rand io.Reader) (cA *big.Int, pf *RangeProofAlice, err error) { + // [FORK] Upstream does not validate parameters. Nil pkA or NTilde causes + // nil-pointer panics deep in proof construction. + if ec == nil || pkA == nil || a == nil || NTildeB == nil || h1B == nil || h2B == nil || rand == nil { + return nil, nil, errors.New("AliceInit received nil argument") + } cA, rA, err := pkA.EncryptAndReturnRandomness(rand, a) if err != nil { return nil, nil, err } - pf, err = ProveRangeAlice(ec, pkA, cA, NTildeB, h1B, h2B, a, rA, rand) + pf, err = ProveRangeAlice(Session, ec, pkA, cA, NTildeB, h1B, h2B, a, rA, rand) return cA, pf, err } -func BobMid( - Session []byte, - ec elliptic.Curve, - pkA *paillier.PublicKey, - pf *RangeProofAlice, - b, cA, NTildeA, h1A, h2A, NTildeB, h1B, h2B *big.Int, - rand io.Reader, -) (beta, cB, betaPrm *big.Int, piB *ProofBob, err error) { - if !pf.Verify(ec, pkA, NTildeB, h1B, h2B, cA) { +// [FORK] Split into two session parameters (AliceSession, BobSession) for per-party SSID +// domain separation: Alice's range proof is verified under her session tag, Bob's proof is +// constructed under his. Upstream's AliceInit/ProveRangeAlice has no session parameter at all +// (range proof hash is entirely untagged); only Bob's side has a Session parameter. +func BobMid(AliceSession []byte, BobSession []byte, ec elliptic.Curve, pkA *paillier.PublicKey, pf *RangeProofAlice, b, cA, NTildeA, h1A, h2A, NTildeB, h1B, h2B *big.Int, rand io.Reader) (beta, cB, betaPrm *big.Int, piB *ProofBob, err error) { + // [FORK] Nil parameter guard — upstream does not validate, leading to nil-pointer panics. + if ec == nil || pkA == nil || pf == nil || b == nil || cA == nil || rand == nil { + err = errors.New("BobMid received nil argument") + return + } + if !pf.Verify(AliceSession, ec, pkA, NTildeB, h1B, h2B, cA) { err = errors.New("RangeProofAlice.Verify() returned false") return } @@ -61,20 +64,18 @@ func BobMid( return } beta = common.ModInt(q).Sub(zero, betaPrm) - piB, err = ProveBob(Session, ec, pkA, NTildeA, h1A, h2A, cA, cB, b, betaPrm, cRand, rand) + piB, err = ProveBob(BobSession, ec, pkA, NTildeA, h1A, h2A, cA, cB, b, betaPrm, cRand, rand) return } -func BobMidWC( - Session []byte, - ec elliptic.Curve, - pkA *paillier.PublicKey, - pf *RangeProofAlice, - b, cA, NTildeA, h1A, h2A, NTildeB, h1B, h2B *big.Int, - B *crypto.ECPoint, - rand io.Reader, -) (beta, cB, betaPrm *big.Int, piB *ProofBobWC, err error) { - if !pf.Verify(ec, pkA, NTildeB, h1B, h2B, cA) { +// [FORK] Same per-party session split as BobMid above, plus nil parameter guards. +func BobMidWC(AliceSession []byte, BobSession []byte, ec elliptic.Curve, pkA *paillier.PublicKey, pf *RangeProofAlice, b, cA, NTildeA, h1A, h2A, NTildeB, h1B, h2B *big.Int, B *crypto.ECPoint, rand io.Reader) (beta, cB, betaPrm *big.Int, piB *ProofBobWC, err error) { + // [FORK] Nil parameter guard — upstream does not validate. + if ec == nil || pkA == nil || pf == nil || b == nil || cA == nil || B == nil || rand == nil { + err = errors.New("BobMidWC received nil argument") + return + } + if !pf.Verify(AliceSession, ec, pkA, NTildeB, h1B, h2B, cA) { err = errors.New("RangeProofAlice.Verify() returned false") return } @@ -96,18 +97,11 @@ func BobMidWC( return } beta = common.ModInt(q).Sub(zero, betaPrm) - piB, err = ProveBobWC(Session, ec, pkA, NTildeA, h1A, h2A, cA, cB, b, betaPrm, cRand, B, rand) + piB, err = ProveBobWC(BobSession, ec, pkA, NTildeA, h1A, h2A, cA, cB, b, betaPrm, cRand, B, rand) return } -func AliceEnd( - Session []byte, - ec elliptic.Curve, - pkA *paillier.PublicKey, - pf *ProofBob, - h1A, h2A, cA, cB, NTildeA *big.Int, - sk *paillier.PrivateKey, -) (*big.Int, error) { +func AliceEnd(Session []byte, ec elliptic.Curve, pkA *paillier.PublicKey, pf *ProofBob, h1A, h2A, cA, cB, NTildeA *big.Int, sk *paillier.PrivateKey) (*big.Int, error) { if !pf.Verify(Session, ec, pkA, NTildeA, h1A, h2A, cA, cB) { return nil, errors.New("ProofBob.Verify() returned false") } @@ -119,15 +113,7 @@ func AliceEnd( return new(big.Int).Mod(alphaPrm, q), nil } -func AliceEndWC( - Session []byte, - ec elliptic.Curve, - pkA *paillier.PublicKey, - pf *ProofBobWC, - B *crypto.ECPoint, - cA, cB, NTildeA, h1A, h2A *big.Int, - sk *paillier.PrivateKey, -) (*big.Int, error) { +func AliceEndWC(Session []byte, ec elliptic.Curve, pkA *paillier.PublicKey, pf *ProofBobWC, B *crypto.ECPoint, cA, cB, NTildeA, h1A, h2A *big.Int, sk *paillier.PrivateKey) (*big.Int, error) { if !pf.Verify(Session, ec, pkA, NTildeA, h1A, h2A, cA, cB, B) { return nil, errors.New("ProofBobWC.Verify() returned false") } diff --git a/tss-lib/crypto/mta/share_protocol_test.go b/tss-lib/crypto/mta/share_protocol_test.go deleted file mode 100644 index ae6ced1..0000000 --- a/tss-lib/crypto/mta/share_protocol_test.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package mta - -import ( - "context" - "crypto/rand" - "math/big" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Using a modulus length of 2048 is recommended in the GG18 spec -const ( - testPaillierKeyLength = 2048 -) - -var Session = []byte("session") - -func TestShareProtocol(t *testing.T) { - q := tss.EC().Params().N - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - sk, pk, err := paillier.GenerateKeyPair(ctx, rand.Reader, testPaillierKeyLength) - assert.NoError(t, err) - - a := common.GetRandomPositiveInt(rand.Reader, q) - b := common.GetRandomPositiveInt(rand.Reader, q) - - NTildei, h1i, h2i, err := keygen.LoadNTildeH1H2FromTestFixture(0) - assert.NoError(t, err) - NTildej, h1j, h2j, err := keygen.LoadNTildeH1H2FromTestFixture(1) - assert.NoError(t, err) - - cA, pf, err := AliceInit(tss.EC(), pk, a, NTildej, h1j, h2j, rand.Reader) - assert.NoError(t, err) - - _, cB, betaPrm, pfB, err := BobMid(Session, tss.EC(), pk, pf, b, cA, NTildei, h1i, h2i, NTildej, h1j, h2j, rand.Reader) - assert.NoError(t, err) - - alpha, err := AliceEnd(Session, tss.EC(), pk, pfB, h1i, h2i, cA, cB, NTildei, sk) - assert.NoError(t, err) - - // expect: alpha = ab + betaPrm - aTimesB := new(big.Int).Mul(a, b) - aTimesBPlusBeta := new(big.Int).Add(aTimesB, betaPrm) - aTimesBPlusBetaModQ := new(big.Int).Mod(aTimesBPlusBeta, q) - assert.Equal(t, 0, alpha.Cmp(aTimesBPlusBetaModQ)) -} - -func TestShareProtocolWC(t *testing.T) { - q := tss.EC().Params().N - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - sk, pk, err := paillier.GenerateKeyPair(ctx, rand.Reader, testPaillierKeyLength) - assert.NoError(t, err) - - a := common.GetRandomPositiveInt(rand.Reader, q) - b := common.GetRandomPositiveInt(rand.Reader, q) - gBX, gBY := tss.EC().ScalarBaseMult(b.Bytes()) - - NTildei, h1i, h2i, err := keygen.LoadNTildeH1H2FromTestFixture(0) - assert.NoError(t, err) - NTildej, h1j, h2j, err := keygen.LoadNTildeH1H2FromTestFixture(1) - assert.NoError(t, err) - - cA, pf, err := AliceInit(tss.EC(), pk, a, NTildej, h1j, h2j, rand.Reader) - assert.NoError(t, err) - - gBPoint, err := crypto.NewECPoint(tss.EC(), gBX, gBY) - assert.NoError(t, err) - _, cB, betaPrm, pfB, err := BobMidWC(Session, tss.EC(), pk, pf, b, cA, NTildei, h1i, h2i, NTildej, h1j, h2j, gBPoint, rand.Reader) - assert.NoError(t, err) - - alpha, err := AliceEndWC(Session, tss.EC(), pk, pfB, gBPoint, cA, cB, NTildei, h1i, h2i, sk) - assert.NoError(t, err) - - // expect: alpha = ab + betaPrm - aTimesB := new(big.Int).Mul(a, b) - aTimesBPlusBeta := new(big.Int).Add(aTimesB, betaPrm) - aTimesBPlusBetaModQ := new(big.Int).Mod(aTimesBPlusBeta, q) - assert.Equal(t, 0, alpha.Cmp(aTimesBPlusBetaModQ)) -} diff --git a/tss-lib/crypto/paillier/coverage_test.go b/tss-lib/crypto/paillier/coverage_test.go new file mode 100644 index 0000000..871a02e --- /dev/null +++ b/tss-lib/crypto/paillier/coverage_test.go @@ -0,0 +1,25 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package paillier + +import ( + "math/big" + "testing" +) + +func TestPublicKeyAsInts(t *testing.T) { + pk := &PublicKey{N: big.NewInt(100)} + ints := pk.AsInts() + if len(ints) != 2 { + t.Fatalf("expected 2 ints, got %d", len(ints)) + } + if ints[0].Cmp(big.NewInt(100)) != 0 { + t.Fatalf("N mismatch: got %v", ints[0]) + } + // Gamma = N+1 = 101 + if ints[1].Cmp(big.NewInt(101)) != 0 { + t.Fatalf("Gamma mismatch: got %v", ints[1]) + } +} diff --git a/tss-lib/crypto/paillier/negative_test.go b/tss-lib/crypto/paillier/negative_test.go new file mode 100644 index 0000000..d4c5c21 --- /dev/null +++ b/tss-lib/crypto/paillier/negative_test.go @@ -0,0 +1,163 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package paillier + +import ( + "context" + "crypto/rand" + "math/big" + "testing" + + crypto2 "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// --- HomoMult error paths --- + +func TestHomoMultNegativeM(t *testing.T) { + pk := &PublicKey{N: big.NewInt(100)} + _, err := pk.HomoMult(big.NewInt(-1), big.NewInt(5)) + if err == nil { + t.Fatal("expected error for negative m") + } +} + +func TestHomoMultMTooLarge(t *testing.T) { + pk := &PublicKey{N: big.NewInt(100)} + _, err := pk.HomoMult(big.NewInt(100), big.NewInt(5)) + if err == nil { + t.Fatal("expected error for m >= N") + } +} + +func TestHomoMultC1Negative(t *testing.T) { + pk := &PublicKey{N: big.NewInt(100)} + _, err := pk.HomoMult(big.NewInt(1), big.NewInt(-5)) + if err == nil { + t.Fatal("expected error for negative c1") + } +} + +func TestHomoMultC1GCDFails(t *testing.T) { + // c1 shares a factor with N → GCD != 1 + pk := &PublicKey{N: big.NewInt(15)} // 3*5 + N2 := pk.NSquare() + c1 := big.NewInt(3) // shares factor 3 with N=15 + if c1.Cmp(N2) >= 0 { + t.Skip("c1 too large") + } + _, err := pk.HomoMult(big.NewInt(1), c1) + if err == nil { + t.Fatal("expected error for c1 sharing factor with N") + } +} + +// --- HomoAdd error paths --- + +func TestHomoAddC1Negative(t *testing.T) { + pk := &PublicKey{N: big.NewInt(100)} + _, err := pk.HomoAdd(big.NewInt(-1), big.NewInt(5)) + if err == nil { + t.Fatal("expected error for negative c1") + } +} + +func TestHomoAddC2Negative(t *testing.T) { + pk := &PublicKey{N: big.NewInt(100)} + _, err := pk.HomoAdd(big.NewInt(5), big.NewInt(-1)) + if err == nil { + t.Fatal("expected error for negative c2") + } +} + +func TestHomoAddC1GCDFails(t *testing.T) { + pk := &PublicKey{N: big.NewInt(15)} + _, err := pk.HomoAdd(big.NewInt(3), big.NewInt(1)) + if err == nil { + t.Fatal("expected error for c1 sharing factor with N") + } +} + +func TestHomoAddC2GCDFails(t *testing.T) { + pk := &PublicKey{N: big.NewInt(15)} + _, err := pk.HomoAdd(big.NewInt(1), big.NewInt(3)) + if err == nil { + t.Fatal("expected error for c2 sharing factor with N") + } +} + +// --- EncryptAndReturnRandomness error path --- + +func TestEncryptNegativeMessage(t *testing.T) { + sk, pk, err := GenerateKeyPair(context.Background(), rand.Reader, 512) + if err != nil { + t.Fatalf("GenerateKeyPair: %v", err) + } + _ = sk + _, _, err = pk.EncryptAndReturnRandomness(rand.Reader, big.NewInt(-1)) + if err == nil { + t.Fatal("expected error for negative message") + } +} + +// --- Decrypt error path --- + +func TestDecryptOutOfRange(t *testing.T) { + sk, _, err := GenerateKeyPair(context.Background(), rand.Reader, 512) + if err != nil { + t.Fatalf("GenerateKeyPair: %v", err) + } + // Pass a value >= N^2 + N2 := sk.NSquare() + _, err = sk.Decrypt(N2) + if err == nil { + t.Fatal("expected error for c >= N^2") + } +} + +// --- Proof/Verify with wrong key --- + +func TestVerifyWithWrongKey(t *testing.T) { + sk1, pk1, err := GenerateKeyPair(context.Background(), rand.Reader, 512) + if err != nil { + t.Fatalf("GenerateKeyPair 1: %v", err) + } + _, pk2, err := GenerateKeyPair(context.Background(), rand.Reader, 512) + if err != nil { + t.Fatalf("GenerateKeyPair 2: %v", err) + } + + // Need a k and ecdsaPub for Proof + ec := crypto2.ScalarBaseMult(tss.S256(), big.NewInt(1)) + k := big.NewInt(42) + + proof := sk1.Proof(k, ec) + // Verify with wrong key — should fail + ok, err := proof.Verify(pk2.N, k, ec) + if err == nil && ok { + t.Fatal("proof from different key should fail verification") + } + // Verify with correct key — should pass + ok, err = proof.Verify(pk1.N, k, ec) + if err != nil { + t.Fatalf("Verify error: %v", err) + } + if !ok { + t.Fatal("proof with correct key should pass") + } +} + +// --- GenerateKeyPair with bad concurrency --- + +func TestGenerateKeyPairSmallBits(t *testing.T) { + // Very small modulus, just verify it doesn't hang. + sk, pk, err := GenerateKeyPair(context.Background(), rand.Reader, 128) + if err != nil { + t.Fatalf("GenerateKeyPair: %v", err) + } + if sk == nil || pk == nil { + t.Fatal("expected non-nil keys") + } +} diff --git a/tss-lib/crypto/paillier/paillier.go b/tss-lib/crypto/paillier/paillier.go index ef8eeac..31921c1 100644 --- a/tss-lib/crypto/paillier/paillier.go +++ b/tss-lib/crypto/paillier/paillier.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. // The Paillier Crypto-system is an additive crypto-system. This means that given two ciphertexts, one can perform operations equivalent to adding the respective plain texts. // Additionally, Paillier Crypto-system supports further computations: @@ -27,8 +26,8 @@ import ( "github.com/otiai10/primes" - "github.com/hemilabs/x/tss-lib/v2/common" - crypto2 "github.com/hemilabs/x/tss-lib/v2/crypto" + "github.com/hemilabs/x/tss-lib/v3/common" + crypto2 "github.com/hemilabs/x/tss-lib/v3/crypto" ) const ( @@ -139,6 +138,9 @@ func (publicKey *PublicKey) HomoMult(m, c1 *big.Int) (*big.Int, error) { if c1.Cmp(zero) == -1 || c1.Cmp(N2) != -1 { // c1 < 0 || c1 >= N2 ? return nil, ErrMessageTooLong } + if new(big.Int).GCD(nil, nil, c1, publicKey.N).Cmp(one) != 0 { + return nil, ErrMessageMalFormed + } // cipher^m mod N2 return common.ModInt(N2).Exp(c1, m), nil } @@ -151,6 +153,12 @@ func (publicKey *PublicKey) HomoAdd(c1, c2 *big.Int) (*big.Int, error) { if c2.Cmp(zero) == -1 || c2.Cmp(N2) != -1 { // c2 < 0 || c2 >= N2 ? return nil, ErrMessageTooLong } + if new(big.Int).GCD(nil, nil, c1, publicKey.N).Cmp(one) != 0 { + return nil, ErrMessageMalFormed + } + if new(big.Int).GCD(nil, nil, c2, publicKey.N).Cmp(one) != 0 { + return nil, ErrMessageMalFormed + } // c1 * c2 mod N2 return common.ModInt(N2).Mul(c1, c2), nil } @@ -186,6 +194,9 @@ func (privateKey *PrivateKey) Decrypt(c *big.Int) (m *big.Int, err error) { Lg := L(new(big.Int).Exp(privateKey.Gamma(), privateKey.LambdaN, N2), privateKey.N) // 3. (1) * modInv(2) mod N inv := new(big.Int).ModInverse(Lg, privateKey.N) + if inv == nil { + return nil, ErrMessageMalFormed + } m = common.ModInt(privateKey.N).Mul(Lc, inv) return } @@ -200,14 +211,27 @@ func (privateKey *PrivateKey) Proof(k *big.Int, ecdsaPub *crypto2.ECPoint) Proof var pi Proof iters := ProofIters xs := GenerateXs(iters, k, privateKey.N, ecdsaPub) + M := new(big.Int).ModInverse(privateKey.N, privateKey.PhiN) + // [FORK] Upstream does not check for nil ModInverse. If N is not coprime + // with PhiN (degenerate key), ModInverse returns nil and Exp panics. + if M == nil { + return pi // N not coprime with PhiN, degenerate key + } for i := 0; i < iters; i++ { - M := new(big.Int).ModInverse(privateKey.N, privateKey.PhiN) pi[i] = new(big.Int).Exp(xs[i], M, privateKey.N) } return pi } func (pf Proof) Verify(pkN, k *big.Int, ecdsaPub *crypto2.ECPoint) (bool, error) { + // [FORK] Defense-in-depth: reject proofs with nil elements to prevent + // nil-pointer panics from degenerate keys or malformed messages. + // Upstream does not validate proof elements before use. + for i := 0; i < ProofIters; i++ { + if pf[i] == nil { + return false, fmt.Errorf("paillier proof element %d is nil", i) + } + } iters := ProofIters pch, xch := make(chan bool, 1), make(chan []*big.Int, 1) // buffered to allow early exit prms := primes.Until(verifyPrimesUntil).List() // uses cache primed in init() @@ -279,7 +303,7 @@ func GenerateXs(m int, k, N *big.Int, ecdsaPub *crypto2.ECPoint) []*big.Int { for _, ch := range chs { // must be in order rx := <-ch if rx == nil { // this should never happen. see: https://golang.org/pkg/hash/#Hash - panic(errors.New("GenerateXs hash write error!")) + panic(errors.New("generateXs hash write error")) } xi = append(xi, rx...) // xi1||···||xib } diff --git a/tss-lib/crypto/paillier/paillier_test.go b/tss-lib/crypto/paillier/paillier_test.go index 136e274..e715abe 100644 --- a/tss-lib/crypto/paillier/paillier_test.go +++ b/tss-lib/crypto/paillier/paillier_test.go @@ -10,15 +10,14 @@ import ( "context" "crypto/rand" "math/big" + "reflect" "testing" "time" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - . "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + . "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" ) // Using a modulus length of 2048 is recommended in the GG18 spec @@ -41,21 +40,31 @@ func setUp(t *testing.T) { var err error privateKey, publicKey, err = GenerateKeyPair(ctx, rand.Reader, testPaillierKeyLength) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } } func TestGenerateKeyPair(t *testing.T) { setUp(t) - assert.NotZero(t, publicKey) - assert.NotZero(t, privateKey) + if publicKey == nil { + t.Fatal("expected non-zero") + } + if privateKey == nil { + t.Fatal("expected non-zero") + } t.Log(privateKey) } func TestEncrypt(t *testing.T) { setUp(t) cipher, err := publicKey.Encrypt(rand.Reader, big.NewInt(1)) - assert.NoError(t, err, "must not error") - assert.NotZero(t, cipher) + if err != nil { + t.Fatalf("must not error"+": %v", err) + } + if cipher == nil { + t.Fatal("expected non-zero") + } t.Log(cipher) } @@ -67,31 +76,44 @@ func TestEncryptDecrypt(t *testing.T) { t.Error(err) } ret, err := privateKey.Decrypt(cypher) - assert.NoError(t, err) - assert.Equal(t, 0, exp.Cmp(ret), - "wrong decryption ", ret, " is not ", exp) + if err != nil { + t.Fatal(err) + } + if exp.Cmp(ret) != 0 { + t.Fatalf("wrong decryption: got %v, want %v", ret, exp) + } cypher = new(big.Int).Set(privateKey.N) _, err = privateKey.Decrypt(cypher) - assert.Error(t, err) + if err == nil { + t.Fatal("expected error") + } } func TestHomoMul(t *testing.T) { setUp(t) three, err := privateKey.Encrypt(rand.Reader, big.NewInt(3)) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } // for HomoMul, the first argument `m` is not ciphered six := big.NewInt(6) cm, err := privateKey.HomoMult(six, three) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } multiple, err := privateKey.Decrypt(cm) - assert.NoError(t, err) + if err != nil { + t.Fatal(err) + } // 3 * 6 = 18 exp := int64(18) - assert.Equal(t, 0, multiple.Cmp(big.NewInt(exp))) + if multiple.Cmp(big.NewInt(exp)) != 0 { + t.Fatalf("got %v, want %v", multiple.Cmp(big.NewInt(exp)), 0) + } } func TestHomoAdd(t *testing.T) { @@ -106,7 +128,9 @@ func TestHomoAdd(t *testing.T) { plain, _ := privateKey.Decrypt(ciphered) - assert.Equal(t, new(big.Int).Add(num1, num2), plain) + if !reflect.DeepEqual(new(big.Int).Add(num1, num2), plain) { + t.Fatalf("got %v, want %v", plain, new(big.Int).Add(num1, num2)) + } } func TestProofVerify(t *testing.T) { @@ -116,8 +140,12 @@ func TestProofVerify(t *testing.T) { yX, yY := tss.EC().ScalarBaseMult(ui.Bytes()) // ECDSA public proof := privateKey.Proof(ki, crypto.NewECPointNoCurveCheck(tss.EC(), yX, yY)) res, err := proof.Verify(publicKey.N, ki, crypto.NewECPointNoCurveCheck(tss.EC(), yX, yY)) - assert.NoError(t, err) - assert.True(t, res, "proof verify result must be true") + if err != nil { + t.Fatal(err) + } + if !res { + t.Fatal("proof verify result must be true") + } } func TestProofVerifyFail(t *testing.T) { @@ -129,8 +157,12 @@ func TestProofVerifyFail(t *testing.T) { last := proof[len(proof)-1] last.Sub(last, big.NewInt(1)) res, err := proof.Verify(publicKey.N, ki, crypto.NewECPointNoCurveCheck(tss.EC(), yX, yY)) - assert.NoError(t, err) - assert.False(t, res, "proof verify result must be true") + if err != nil { + t.Fatal(err) + } + if res { + t.Fatal("proof verify result must be true") + } } func TestComputeL(t *testing.T) { @@ -140,7 +172,9 @@ func TestComputeL(t *testing.T) { expected := big.NewInt(6) actual := L(u, n) - assert.Equal(t, 0, expected.Cmp(actual)) + if expected.Cmp(actual) != 0 { + t.Fatalf("got %v, want %v", expected.Cmp(actual), 0) + } } func TestGenerateXs(t *testing.T) { @@ -150,8 +184,12 @@ func TestGenerateXs(t *testing.T) { N := common.GetRandomPrimeInt(rand.Reader, 2048) xs := GenerateXs(13, k, N, crypto.NewECPointNoCurveCheck(tss.EC(), sX, sY)) - assert.Equal(t, 13, len(xs)) + if len(xs) != 13 { + t.Fatalf("got %v, want %v", len(xs), 13) + } for _, xi := range xs { - assert.True(t, common.IsNumberInMultiplicativeGroup(N, xi)) + if !common.IsNumberInMultiplicativeGroup(N, xi) { + t.Fatal("expected true") + } } } diff --git a/tss-lib/crypto/schnorr/negative_test.go b/tss-lib/crypto/schnorr/negative_test.go new file mode 100644 index 0000000..afd2774 --- /dev/null +++ b/tss-lib/crypto/schnorr/negative_test.go @@ -0,0 +1,88 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package schnorr + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +var negSession = []byte("negative-test") + +func TestNewZKProofNilArgs(t *testing.T) { + _, err := NewZKProof(negSession, nil, nil, rand.Reader) + if err == nil { + t.Fatal("expected error for nil args") + } +} + +func TestZKProofVerifyRejectsWrongSession(t *testing.T) { + ec := tss.S256() + x := big.NewInt(42) + X := crypto.ScalarBaseMult(ec, x) + pf, err := NewZKProof(negSession, x, X, rand.Reader) + if err != nil { + t.Fatalf("NewZKProof: %v", err) + } + if pf.Verify([]byte("wrong-session"), X) { + t.Fatal("wrong session should fail") + } +} + +func TestZKProofVerifyRejectsWrongX(t *testing.T) { + ec := tss.S256() + x := big.NewInt(42) + X := crypto.ScalarBaseMult(ec, x) + pf, err := NewZKProof(negSession, x, X, rand.Reader) + if err != nil { + t.Fatalf("NewZKProof: %v", err) + } + wrongX := crypto.ScalarBaseMult(ec, big.NewInt(99)) + if pf.Verify(negSession, wrongX) { + t.Fatal("wrong X should fail") + } +} + +func TestNewZKVProofNilArgs(t *testing.T) { + _, err := NewZKVProof(negSession, nil, nil, nil, nil, rand.Reader) + if err == nil { + t.Fatal("expected error for nil args") + } +} + +func TestZKVProofVerifyRejectsWrongSession(t *testing.T) { + ec := tss.S256() + s := big.NewInt(42) + l := big.NewInt(7) + V := crypto.ScalarBaseMult(ec, s) + R := crypto.ScalarBaseMult(ec, l) + pf, err := NewZKVProof(negSession, V, R, s, l, rand.Reader) + if err != nil { + t.Fatalf("NewZKVProof: %v", err) + } + if pf.Verify([]byte("wrong"), V, R) { + t.Fatal("wrong session should fail") + } +} + +func TestZKVProofVerifyRejectsWrongR(t *testing.T) { + ec := tss.S256() + s := big.NewInt(42) + l := big.NewInt(7) + V := crypto.ScalarBaseMult(ec, s) + R := crypto.ScalarBaseMult(ec, l) + pf, err := NewZKVProof(negSession, V, R, s, l, rand.Reader) + if err != nil { + t.Fatalf("NewZKVProof: %v", err) + } + wrongR := crypto.ScalarBaseMult(ec, big.NewInt(99)) + if pf.Verify(negSession, V, wrongR) { + t.Fatal("wrong R should fail") + } +} diff --git a/tss-lib/crypto/schnorr/schnorr_fork_test.go b/tss-lib/crypto/schnorr/schnorr_fork_test.go new file mode 100644 index 0000000..5743960 --- /dev/null +++ b/tss-lib/crypto/schnorr/schnorr_fork_test.go @@ -0,0 +1,209 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package schnorr_test + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +var forkSession = []byte("fork-session") + +// TestZKProofRejectsTEqualToQ verifies that ZKProof.Verify rejects a proof +// where T has been tampered to equal q (the curve order). The fork's range +// check (T < q) must catch this. +func TestZKProofRejectsTEqualToQ(t *testing.T) { + q := tss.S256().Params().N + x := common.GetRandomPositiveInt(rand.Reader, q) + X := crypto.ScalarBaseMult(tss.S256(), x) + + pf, err := schnorr.NewZKProof(forkSession, x, X, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(forkSession, X) { + t.Fatal("honest proof must verify") + } + + // Tamper: set T = q (out of range [0, q)). + pf.T = new(big.Int).Set(q) + if pf.Verify(forkSession, X) { + t.Fatal("proof with T == q must be rejected") + } +} + +// TestZKProofRejectsTGreaterThanQ verifies that ZKProof.Verify rejects a proof +// where T has been shifted by +q. Since T + q is congruent to T mod q, the +// algebraic check would pass without the range check. +func TestZKProofRejectsTGreaterThanQ(t *testing.T) { + q := tss.S256().Params().N + x := common.GetRandomPositiveInt(rand.Reader, q) + X := crypto.ScalarBaseMult(tss.S256(), x) + + pf, err := schnorr.NewZKProof(forkSession, x, X, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Tamper: set T = T + q (congruent mod q, but out of range). + pf.T = new(big.Int).Add(pf.T, q) + if pf.Verify(forkSession, X) { + t.Fatal("proof with T >= q must be rejected") + } +} + +// TestZKProofRejectsNegativeT verifies that ZKProof.Verify rejects a proof +// where T is negative (Sign() < 0 check in the fork). +func TestZKProofRejectsNegativeT(t *testing.T) { + q := tss.S256().Params().N + x := common.GetRandomPositiveInt(rand.Reader, q) + X := crypto.ScalarBaseMult(tss.S256(), x) + + pf, err := schnorr.NewZKProof(forkSession, x, X, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Tamper: set T = -1. + pf.T = big.NewInt(-1) + if pf.Verify(forkSession, X) { + t.Fatal("proof with negative T must be rejected") + } +} + +// TestZKVProofRejectsTOutOfRange verifies that ZKVProof.Verify rejects a proof +// where T has been tampered to equal q. +func TestZKVProofRejectsTOutOfRange(t *testing.T) { + q := tss.S256().Params().N + k := common.GetRandomPositiveInt(rand.Reader, q) + s := common.GetRandomPositiveInt(rand.Reader, q) + l := common.GetRandomPositiveInt(rand.Reader, q) + + R := crypto.ScalarBaseMult(tss.S256(), k) + Rs := R.ScalarMult(s) + lG := crypto.ScalarBaseMult(tss.S256(), l) + V, err := Rs.Add(lG) + if err != nil { + t.Fatal(err) + } + + pf, err := schnorr.NewZKVProof(forkSession, V, R, s, l, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(forkSession, V, R) { + t.Fatal("honest ZKVProof must verify") + } + + // Tamper: set T = q. + pf.T = new(big.Int).Set(q) + if pf.Verify(forkSession, V, R) { + t.Fatal("ZKVProof with T == q must be rejected") + } +} + +// TestZKVProofRejectsUOutOfRange verifies that ZKVProof.Verify rejects a proof +// where U has been tampered to equal q. +func TestZKVProofRejectsUOutOfRange(t *testing.T) { + q := tss.S256().Params().N + k := common.GetRandomPositiveInt(rand.Reader, q) + s := common.GetRandomPositiveInt(rand.Reader, q) + l := common.GetRandomPositiveInt(rand.Reader, q) + + R := crypto.ScalarBaseMult(tss.S256(), k) + Rs := R.ScalarMult(s) + lG := crypto.ScalarBaseMult(tss.S256(), l) + V, err := Rs.Add(lG) + if err != nil { + t.Fatal(err) + } + + pf, err := schnorr.NewZKVProof(forkSession, V, R, s, l, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Sanity: honest proof verifies. + if !pf.Verify(forkSession, V, R) { + t.Fatal("honest ZKVProof must verify") + } + + // Tamper: set U = q. + pf.U = new(big.Int).Set(q) + if pf.Verify(forkSession, V, R) { + t.Fatal("ZKVProof with U == q must be rejected") + } +} + +// TestZKProofRejectsWrongSession verifies that a ZKProof generated with one +// session tag is rejected when verified with a different session tag. +func TestZKProofRejectsWrongSession(t *testing.T) { + sessionA := []byte("session-A") + sessionB := []byte("session-B") + + q := tss.S256().Params().N + x := common.GetRandomPositiveInt(rand.Reader, q) + X := crypto.ScalarBaseMult(tss.S256(), x) + + pf, err := schnorr.NewZKProof(sessionA, x, X, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Sanity: proof verifies with the correct session. + if !pf.Verify(sessionA, X) { + t.Fatal("proof must verify with correct session") + } + + // Cross-session: proof must not verify with a different session. + if pf.Verify(sessionB, X) { + t.Fatal("proof must be rejected with wrong session") + } +} + +// TestZKVProofRejectsWrongSession verifies that a ZKVProof generated with one +// session tag is rejected when verified with a different session tag. +func TestZKVProofRejectsWrongSession(t *testing.T) { + sessionA := []byte("session-A") + sessionB := []byte("session-B") + + q := tss.S256().Params().N + k := common.GetRandomPositiveInt(rand.Reader, q) + s := common.GetRandomPositiveInt(rand.Reader, q) + l := common.GetRandomPositiveInt(rand.Reader, q) + + R := crypto.ScalarBaseMult(tss.S256(), k) + Rs := R.ScalarMult(s) + lG := crypto.ScalarBaseMult(tss.S256(), l) + V, err := Rs.Add(lG) + if err != nil { + t.Fatal(err) + } + + pf, err := schnorr.NewZKVProof(sessionA, V, R, s, l, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Sanity: proof verifies with the correct session. + if !pf.Verify(sessionA, V, R) { + t.Fatal("ZKVProof must verify with correct session") + } + + // Cross-session: proof must not verify with a different session. + if pf.Verify(sessionB, V, R) { + t.Fatal("ZKVProof must be rejected with wrong session") + } +} diff --git a/tss-lib/crypto/schnorr/schnorr_proof.go b/tss-lib/crypto/schnorr/schnorr_proof.go index 5cafc36..e6e52c8 100644 --- a/tss-lib/crypto/schnorr/schnorr_proof.go +++ b/tss-lib/crypto/schnorr/schnorr_proof.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package schnorr @@ -11,8 +10,8 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" ) type ( @@ -27,7 +26,8 @@ type ( } ) -// NewZKProof constructs a new Schnorr ZK proof of knowledge of the discrete logarithm (GG18Spec Fig. 16) +// NewZKProof constructs a new Schnorr ZK proof of knowledge of the discrete logarithm (GG18Spec Fig. 16). +// Session provides SSID domain separation (replay prevention across ceremonies). func NewZKProof(Session []byte, x *big.Int, X *crypto.ECPoint, rand io.Reader) (*ZKProof, error) { if x == nil || X == nil || !X.ValidateBasic() { return nil, errors.New("ZKProof constructor received nil or invalid value(s)") @@ -53,21 +53,35 @@ func NewZKProof(Session []byte, x *big.Int, X *crypto.ECPoint, rand io.Reader) ( // NewZKProof verifies a new Schnorr ZK proof of knowledge of the discrete logarithm (GG18Spec Fig. 16) func (pf *ZKProof) Verify(Session []byte, X *crypto.ECPoint) bool { - if pf == nil || !pf.ValidateBasic() { + if pf == nil || !pf.ValidateBasic() || X == nil || !X.ValidateBasic() { return false } ec := X.Curve() ecParams := ec.Params() q := ecParams.N + // [FORK] Reject proof scalars outside (0, q) to prevent malleability (T + k*q verifies identically) + // and to guard against zero scalars that would produce identity points in ScalarBaseMult/ScalarMult. + // Upstream does not perform this range check. + if pf.T.Sign() <= 0 || pf.T.Cmp(q) >= 0 { + return false + } g := crypto.NewECPointNoCurveCheck(ec, ecParams.Gx, ecParams.Gy) var c *big.Int { + // SHA512_256i_TAGGED with Session for SSID domain separation. cHash := common.SHA512_256i_TAGGED(Session, X.X(), X.Y(), g.X(), g.Y(), pf.Alpha.X(), pf.Alpha.Y()) c = common.RejectionSample(q, cHash) } + // [FORK] Guard c=0 before ScalarMult to prevent identity-point panic. + // RejectionSample returns values in [0, q), so c=0 is possible (probability ~2^-256). + if c.Sign() == 0 { + return false + } tG := crypto.ScalarBaseMult(ec, pf.T) Xc := X.ScalarMult(c) + // Error handling on Add() (same as upstream): if the result is the identity point, + // NewECPoint returns (nil, error) and the subsequent .X() call would panic. aXc, err := pf.Alpha.Add(Xc) if err != nil { return false @@ -76,7 +90,7 @@ func (pf *ZKProof) Verify(Session []byte, X *crypto.ECPoint) bool { } func (pf *ZKProof) ValidateBasic() bool { - return pf.T != nil && pf.Alpha != nil + return pf.T != nil && pf.Alpha != nil && pf.Alpha.ValidateBasic() } // NewZKProof constructs a new Schnorr ZK proof of knowledge s_i, l_i such that V_i = R^s_i, g^l_i (GG18Spec Fig. 17) @@ -92,7 +106,12 @@ func NewZKVProof(Session []byte, V, R *crypto.ECPoint, s, l *big.Int, rand io.Re a, b := common.GetRandomPositiveInt(rand, q), common.GetRandomPositiveInt(rand, q) aR := R.ScalarMult(a) bG := crypto.ScalarBaseMult(ec, b) - alpha, _ := aR.Add(bG) // already on the curve. + // [FORK] Upstream discards the error: `alpha, _ := aR.Add(bG)`. If the sum is + // the identity point, alpha is nil and the subsequent alpha.X() panics. + alpha, err := aR.Add(bG) + if err != nil { + return nil, errors.New("ZKVProof: aR + bG yielded an invalid point") + } var c *big.Int { @@ -107,12 +126,21 @@ func NewZKVProof(Session []byte, V, R *crypto.ECPoint, s, l *big.Int, rand io.Re } func (pf *ZKVProof) Verify(Session []byte, V, R *crypto.ECPoint) bool { - if pf == nil || !pf.ValidateBasic() { + if pf == nil || !pf.ValidateBasic() || V == nil || !V.ValidateBasic() || R == nil || !R.ValidateBasic() { return false } ec := V.Curve() ecParams := ec.Params() q := ecParams.N + // [FORK] Reject proof scalars outside (0, q) to prevent malleability and guard against + // zero scalars that would produce identity points in ScalarMult/ScalarBaseMult. + // Upstream does not perform these range checks. + if pf.T.Sign() <= 0 || pf.T.Cmp(q) >= 0 { + return false + } + if pf.U.Sign() <= 0 || pf.U.Cmp(q) >= 0 { + return false + } g := crypto.NewECPointNoCurveCheck(ec, ecParams.Gx, ecParams.Gy) var c *big.Int @@ -120,9 +148,18 @@ func (pf *ZKVProof) Verify(Session []byte, V, R *crypto.ECPoint) bool { cHash := common.SHA512_256i_TAGGED(Session, V.X(), V.Y(), R.X(), R.Y(), g.X(), g.Y(), pf.Alpha.X(), pf.Alpha.Y()) c = common.RejectionSample(q, cHash) } + // [FORK] Guard c=0 before ScalarMult to prevent identity-point panic. + if c.Sign() == 0 { + return false + } tR := R.ScalarMult(pf.T) uG := crypto.ScalarBaseMult(ec, pf.U) - tRuG, _ := tR.Add(uG) // already on the curve. + // [FORK] Upstream discards the error: `tRuG, _ := tR.Add(uG)`. If the sum is + // the identity point, tRuG is nil and the subsequent .X() call panics. + tRuG, err := tR.Add(uG) + if err != nil { + return false + } Vc := V.ScalarMult(c) aVc, err := pf.Alpha.Add(Vc) diff --git a/tss-lib/crypto/schnorr/schnorr_proof_test.go b/tss-lib/crypto/schnorr/schnorr_proof_test.go index af6bcc3..1c20e50 100644 --- a/tss-lib/crypto/schnorr/schnorr_proof_test.go +++ b/tss-lib/crypto/schnorr/schnorr_proof_test.go @@ -10,12 +10,10 @@ import ( "crypto/rand" "testing" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - . "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + . "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" ) var Session = []byte("session") @@ -26,10 +24,18 @@ func TestSchnorrProof(t *testing.T) { uG := crypto.ScalarBaseMult(tss.EC(), u) proof, _ := NewZKProof(Session, u, uG, rand.Reader) - assert.True(t, proof.Alpha.IsOnCurve()) - assert.NotZero(t, proof.Alpha.X()) - assert.NotZero(t, proof.Alpha.Y()) - assert.NotZero(t, proof.T) + if !proof.Alpha.IsOnCurve() { + t.Fatal("expected true") + } + if proof.Alpha.X() == nil { + t.Fatal("expected non-zero") + } + if proof.Alpha.Y() == nil { + t.Fatal("expected non-zero") + } + if proof.T == nil { + t.Fatal("expected non-zero") + } } func TestSchnorrProofVerify(t *testing.T) { @@ -40,7 +46,9 @@ func TestSchnorrProofVerify(t *testing.T) { proof, _ := NewZKProof(Session, u, X, rand.Reader) res := proof.Verify(Session, X) - assert.True(t, res, "verify result must be true") + if !res { + t.Fatal("verify result must be true") + } } func TestSchnorrProofVerifyBadX(t *testing.T) { @@ -53,7 +61,9 @@ func TestSchnorrProofVerifyBadX(t *testing.T) { proof, _ := NewZKProof(Session, u2, X2, rand.Reader) res := proof.Verify(Session, X) - assert.False(t, res, "verify result must be false") + if res { + t.Fatal("verify result must be false") + } } func TestSchnorrVProofVerify(t *testing.T) { @@ -69,7 +79,9 @@ func TestSchnorrVProofVerify(t *testing.T) { proof, _ := NewZKVProof(Session, V, R, s, l, rand.Reader) res := proof.Verify(Session, V, R) - assert.True(t, res, "verify result must be true") + if !res { + t.Fatal("verify result must be true") + } } func TestSchnorrVProofVerifyBadPartialV(t *testing.T) { @@ -84,7 +96,9 @@ func TestSchnorrVProofVerifyBadPartialV(t *testing.T) { proof, _ := NewZKVProof(Session, V, R, s, l, rand.Reader) res := proof.Verify(Session, V, R) - assert.False(t, res, "verify result must be false") + if res { + t.Fatal("verify result must be false") + } } func TestSchnorrVProofVerifyBadS(t *testing.T) { @@ -101,5 +115,7 @@ func TestSchnorrVProofVerifyBadS(t *testing.T) { proof, _ := NewZKVProof(Session, V, R, s2, l, rand.Reader) res := proof.Verify(Session, V, R) - assert.False(t, res, "verify result must be false") + if res { + t.Fatal("verify result must be false") + } } diff --git a/tss-lib/crypto/utils.go b/tss-lib/crypto/utils.go index cf8447f..93dda08 100644 --- a/tss-lib/crypto/utils.go +++ b/tss-lib/crypto/utils.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package crypto @@ -11,7 +10,7 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) func GenerateNTildei(rand io.Reader, safePrimes [2]*big.Int) (NTildei, h1i, h2i *big.Int, err error) { @@ -21,6 +20,12 @@ func GenerateNTildei(rand io.Reader, safePrimes [2]*big.Int) (NTildei, h1i, h2i if !safePrimes[0].ProbablyPrime(30) || !safePrimes[1].ProbablyPrime(30) { return nil, nil, nil, fmt.Errorf("GenerateNTildei: expected two primes") } + // [FORK] Upstream does not check for equal primes. If p == q, NTilde = p^2 + // which is trivially factorable, completely breaking Pedersen commitment + // hiding/binding and all range proofs that rely on the hardness of factoring NTilde. + if safePrimes[0].Cmp(safePrimes[1]) == 0 { + return nil, nil, nil, fmt.Errorf("GenerateNTildei: the two primes must be distinct") + } NTildei = new(big.Int).Mul(safePrimes[0], safePrimes[1]) h1 := common.GetRandomGeneratorOfTheQuadraticResidue(rand, NTildei) h2 := common.GetRandomGeneratorOfTheQuadraticResidue(rand, NTildei) diff --git a/tss-lib/crypto/utils_fork_test.go b/tss-lib/crypto/utils_fork_test.go new file mode 100644 index 0000000..e60366d --- /dev/null +++ b/tss-lib/crypto/utils_fork_test.go @@ -0,0 +1,77 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package crypto + +import ( + "crypto/rand" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/common" +) + +func TestGenerateNTildeiRejectsEqualPrimes(t *testing.T) { + // [FORK] Equal primes make NTilde = p^2, trivially factorable + // Use a small safe prime for speed + p := common.GetRandomPrimeInt(rand.Reader, 512) + primes := [2]*big.Int{p, p} // same prime twice + + _, _, _, err := GenerateNTildei(rand.Reader, primes) + if err == nil { + t.Fatal("equal primes should be rejected") + } + if !strings.Contains(err.Error(), "distinct") { + t.Fatalf("expected %q to contain %q", err.Error(), "distinct") + } +} + +func TestGenerateNTildeiRejectsNilPrimes(t *testing.T) { + _, _, _, err := GenerateNTildei(rand.Reader, [2]*big.Int{nil, big.NewInt(7)}) + if err == nil { + t.Fatal("nil prime should be rejected") + } + + _, _, _, err = GenerateNTildei(rand.Reader, [2]*big.Int{big.NewInt(7), nil}) + if err == nil { + t.Fatal("nil prime should be rejected") + } +} + +func TestGenerateNTildeiRejectsNonPrime(t *testing.T) { + _, _, _, err := GenerateNTildei(rand.Reader, [2]*big.Int{big.NewInt(15), big.NewInt(7)}) + if err == nil { + t.Fatal("composite number should be rejected") + } +} + +func TestGenerateNTildeiHappyPath(t *testing.T) { + p := common.GetRandomPrimeInt(rand.Reader, 512) + q := common.GetRandomPrimeInt(rand.Reader, 512) + // Ensure they're different (astronomically unlikely to be same, but be safe) + for p.Cmp(q) == 0 { + q = common.GetRandomPrimeInt(rand.Reader, 512) + } + + NTilde, h1, h2, err := GenerateNTildei(rand.Reader, [2]*big.Int{p, q}) + if err != nil { + t.Fatal(err) + } + if NTilde == nil { + t.Fatal("expected non-nil") + } + if h1 == nil { + t.Fatal("expected non-nil") + } + if h2 == nil { + t.Fatal("expected non-nil") + } + + // NTilde should equal p * q + expected := new(big.Int).Mul(p, q) + if NTilde.Cmp(expected) != 0 { + t.Fatalf("NTilde should be p * q") + } +} diff --git a/tss-lib/crypto/vss/feldman_vss.go b/tss-lib/crypto/vss/feldman_vss.go index 02349eb..9ddb0e2 100644 --- a/tss-lib/crypto/vss/feldman_vss.go +++ b/tss-lib/crypto/vss/feldman_vss.go @@ -1,12 +1,10 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. // Feldman VSS, based on Paul Feldman, 1987., A practical scheme for non-interactive verifiable secret sharing. // In Foundations of Computer Science, 1987., 28th Annual Symposium on. IEEE, 427–43 -// package vss @@ -17,8 +15,8 @@ import ( "io" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" ) type ( @@ -58,23 +56,32 @@ func CheckIndexes(ec elliptic.Curve, indexes []*big.Int) ([]*big.Int, error) { } // Returns a new array of secret shares created by Shamir's Secret Sharing Algorithm, -// requiring a minimum number of shares to recreate, of length shares, from the input secret -func Create(ec elliptic.Curve, threshold int, secret *big.Int, indexes []*big.Int, rand io.Reader) (Vs, Shares, error) { +// requiring a minimum number of shares to recreate, of length shares, from the input secret. +// +// [FORK] Returns the polynomial coefficients as the third return value. Upstream returns +// only (Vs, Shares, error). The polynomial is needed for the per-participant SNARK +// architecture where each operator's SP1 guest must evaluate the polynomial independently. +func Create(ec elliptic.Curve, threshold int, secret *big.Int, indexes []*big.Int, rand io.Reader) (Vs, Shares, []*big.Int, error) { if secret == nil || indexes == nil { - return nil, nil, fmt.Errorf("vss secret or indexes == nil: %v %v", secret, indexes) + return nil, nil, nil, fmt.Errorf("vss secret or indexes == nil: secret=%t indexes=%t", secret != nil, indexes != nil) + } + // [FORK] Reject zero secret: ScalarBaseMult(0) produces the identity point, which + // panics. A zero secret also means the shared key is trivially known (= 0). + if secret.Sign() == 0 { + return nil, nil, nil, errors.New("vss secret must be non-zero") } if threshold < 1 { - return nil, nil, errors.New("vss threshold < 1") + return nil, nil, nil, errors.New("vss threshold < 1") } ids, err := CheckIndexes(ec, indexes) if err != nil { - return nil, nil, err + return nil, nil, nil, err } num := len(indexes) if num < threshold { - return nil, nil, ErrNumSharesBelowThreshold + return nil, nil, nil, ErrNumSharesBelowThreshold } poly := samplePolynomial(ec, threshold, secret, rand) @@ -89,13 +96,26 @@ func Create(ec elliptic.Curve, threshold int, secret *big.Int, indexes []*big.In share := evaluatePolynomial(ec, threshold, poly, ids[i]) shares[i] = &Share{Threshold: threshold, ID: ids[i], Share: share} } - return v, shares, nil + return v, shares, poly, nil } func (share *Share) Verify(ec elliptic.Curve, threshold int, vs Vs) bool { if share.Threshold != threshold || vs == nil || len(vs) != threshold+1 { return false } + // [FORK] Reject shares that are zero or out of range [1, q-1]. + // Upstream does not validate share values, allowing zero shares (which map to the + // identity point under ScalarBaseMult) or out-of-range values (>= q) that indicate + // malformed or tampered data. + q := ec.Params().N + if share.Share == nil || share.Share.Sign() <= 0 || share.Share.Cmp(q) >= 0 { + return false + } + // [FORK] Reject share ID that is nil or zero mod q — evaluation at x=0 leaks the + // secret (constant term of the polynomial). Upstream does not check. + if share.ID == nil || new(big.Int).Mod(share.ID, q).Sign() == 0 { + return false + } var err error modQ := common.ModInt(ec.Params().N) v, t := vs[0], one // YRO : we need to have our accumulator outside of the loop @@ -119,21 +139,40 @@ func (shares Shares) ReConstruct(ec elliptic.Curve) (secret *big.Int, err error) } modN := common.ModInt(ec.Params().N) - // x coords - xs := make([]*big.Int, 0) + // [FORK] Check for duplicate share IDs (reduced mod q) to prevent silently wrong + // Lagrange interpolation. Upstream does not check — duplicate IDs cause division + // by zero in ModInverse. Reduction mod q is necessary because distinct integers + // that are congruent mod q (e.g., k and k+q) produce a zero denominator in the + // Lagrange basis computation. This mirrors the approach in CheckIndexes. + q := ec.Params().N + xs := make([]*big.Int, 0, len(shares)) + seen := make(map[string]struct{}, len(shares)) for _, share := range shares { + idMod := new(big.Int).Mod(share.ID, q) + idStr := idMod.String() + if _, dup := seen[idStr]; dup { + return nil, fmt.Errorf("duplicate share ID %s (mod q) in ReConstruct", idStr) + } + seen[idStr] = struct{}{} xs = append(xs, share.ID) } - secret = zero + secret = new(big.Int) for i, share := range shares { - times := one + times := new(big.Int).SetInt64(1) for j := 0; j < len(xs); j++ { if j == i { continue } sub := modN.Sub(xs[j], share.ID) subInv := modN.ModInverse(sub) + // [FORK] Upstream does not check for nil ModInverse. If share IDs collide + // mod q, ModInverse returns nil causing a nil-pointer panic. + // Defense-in-depth: the mod-q duplicate check above now catches this + // condition, but this nil guard is retained as a safeguard. + if subInv == nil { + return nil, errors.New("ModInverse(xs[j] - share.ID) returned nil; share IDs may collide modulo the curve order") + } div := modN.Mul(xs[j], subInv) times = modN.Mul(times, div) } diff --git a/tss-lib/crypto/vss/feldman_vss_fork_test.go b/tss-lib/crypto/vss/feldman_vss_fork_test.go new file mode 100644 index 0000000..e57bd39 --- /dev/null +++ b/tss-lib/crypto/vss/feldman_vss_fork_test.go @@ -0,0 +1,111 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package vss + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func makeValidShares(t *testing.T) (Vs, Shares) { + t.Helper() + ec := tss.S256() + q := ec.Params().N + secret := common.GetRandomPositiveInt(rand.Reader, q) + indexes := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + vs, shares, _, err := Create(ec, 1, secret, indexes, rand.Reader) + if err != nil { + t.Fatal(err) + } + return vs, shares +} + +func TestVerifyRejectsZeroShare(t *testing.T) { + vs, shares := makeValidShares(t) + share := *shares[0] + share.Share = big.NewInt(0) + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("zero share should be rejected") + } +} + +func TestVerifyRejectsNegativeShare(t *testing.T) { + vs, shares := makeValidShares(t) + share := *shares[0] + share.Share = big.NewInt(-1) + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("negative share should be rejected") + } +} + +func TestVerifyRejectsOutOfRangeShare(t *testing.T) { + vs, shares := makeValidShares(t) + q := tss.S256().Params().N + share := *shares[0] + share.Share = new(big.Int).Set(q) + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("share >= q should be rejected") + } +} + +func TestVerifyRejectsNilShare(t *testing.T) { + vs, shares := makeValidShares(t) + share := *shares[0] + share.Share = nil + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("nil share should be rejected") + } +} + +func TestVerifyRejectsNilShareID(t *testing.T) { + vs, shares := makeValidShares(t) + share := *shares[0] + share.ID = nil + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("nil share ID should be rejected") + } +} + +func TestVerifyRejectsZeroShareID(t *testing.T) { + vs, shares := makeValidShares(t) + share := *shares[0] + share.ID = big.NewInt(0) + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("zero share ID should be rejected") + } +} + +func TestVerifyRejectsShareIDEqualToQ(t *testing.T) { + vs, shares := makeValidShares(t) + q := tss.S256().Params().N + share := *shares[0] + share.ID = new(big.Int).Set(q) + if share.Verify(tss.S256(), 1, vs) { + t.Fatal("share ID == q should be rejected (q mod q == 0)") + } +} + +func TestReconstructRejectsDuplicateIDs(t *testing.T) { + _, shares := makeValidShares(t) + shares[1].ID = new(big.Int).Set(shares[0].ID) + _, err := shares.ReConstruct(tss.S256()) + if err == nil { + t.Fatal("duplicate share IDs should cause ReConstruct to fail") + } +} + +func TestReconstructRejectsDuplicateModQ(t *testing.T) { + _, shares := makeValidShares(t) + q := tss.S256().Params().N + shares[1].ID = new(big.Int).Add(shares[0].ID, q) + _, err := shares.ReConstruct(tss.S256()) + if err == nil { + t.Fatal("share IDs congruent mod q should cause ReConstruct to fail") + } +} diff --git a/tss-lib/crypto/vss/feldman_vss_test.go b/tss-lib/crypto/vss/feldman_vss_test.go index 0fc8e24..a5e745e 100644 --- a/tss-lib/crypto/vss/feldman_vss_test.go +++ b/tss-lib/crypto/vss/feldman_vss_test.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package vss_test @@ -11,11 +10,9 @@ import ( "math/big" "testing" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - . "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/common" + . "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" ) func TestCheckIndexesDup(t *testing.T) { @@ -24,11 +21,15 @@ func TestCheckIndexesDup(t *testing.T) { indexes = append(indexes, common.GetRandomPositiveInt(rand.Reader, tss.EC().Params().N)) } _, e := CheckIndexes(tss.EC(), indexes) - assert.NoError(t, e) + if e != nil { + t.Fatal(e) + } indexes = append(indexes, indexes[99]) _, e = CheckIndexes(tss.EC(), indexes) - assert.Error(t, e) + if e == nil { + t.Fatal("expected error") + } } func TestCheckIndexesZero(t *testing.T) { @@ -37,11 +38,15 @@ func TestCheckIndexesZero(t *testing.T) { indexes = append(indexes, common.GetRandomPositiveInt(rand.Reader, tss.EC().Params().N)) } _, e := CheckIndexes(tss.EC(), indexes) - assert.NoError(t, e) + if e != nil { + t.Fatal(e) + } indexes = append(indexes, tss.EC().Params().N) _, e = CheckIndexes(tss.EC(), indexes) - assert.Error(t, e) + if e == nil { + t.Fatal("expected error") + } } func TestCreate(t *testing.T) { @@ -54,21 +59,37 @@ func TestCreate(t *testing.T) { ids = append(ids, common.GetRandomPositiveInt(rand.Reader, tss.EC().Params().N)) } - vs, _, err := Create(tss.EC(), threshold, secret, ids, rand.Reader) - assert.Nil(t, err) + vs, _, _, err := Create(tss.EC(), threshold, secret, ids, rand.Reader) + if err != nil { + t.Fatalf("expected nil, got %v", err) + } - assert.Equal(t, threshold+1, len(vs)) + if threshold+1 != len(vs) { + t.Fatalf("got %v, want %v", len(vs), threshold+1) + } // assert.Equal(t, num, params.NumShares) - assert.Equal(t, threshold+1, len(vs)) + if threshold+1 != len(vs) { + t.Fatalf("got %v, want %v", len(vs), threshold+1) + } // ensure that each vs has two points on the curve for i, pg := range vs { - assert.NotZero(t, pg.X()) - assert.NotZero(t, pg.Y()) - assert.True(t, pg.IsOnCurve()) - assert.NotZero(t, vs[i].X()) - assert.NotZero(t, vs[i].Y()) + if pg.X() == nil { + t.Fatal("expected non-zero") + } + if pg.Y() == nil { + t.Fatal("expected non-zero") + } + if !pg.IsOnCurve() { + t.Fatal("expected true") + } + if vs[i].X() == nil { + t.Fatal("expected non-zero") + } + if vs[i].Y() == nil { + t.Fatal("expected non-zero") + } } } @@ -82,11 +103,15 @@ func TestVerify(t *testing.T) { ids = append(ids, common.GetRandomPositiveInt(rand.Reader, tss.EC().Params().N)) } - vs, shares, err := Create(tss.EC(), threshold, secret, ids, rand.Reader) - assert.NoError(t, err) + vs, shares, _, err := Create(tss.EC(), threshold, secret, ids, rand.Reader) + if err != nil { + t.Fatal(err) + } for i := 0; i < num; i++ { - assert.True(t, shares[i].Verify(tss.EC(), threshold, vs)) + if !(shares[i].Verify(tss.EC(), threshold, vs)) { + t.Fatal("expected true") + } } } @@ -100,18 +125,32 @@ func TestReconstruct(t *testing.T) { ids = append(ids, common.GetRandomPositiveInt(rand.Reader, tss.EC().Params().N)) } - _, shares, err := Create(tss.EC(), threshold, secret, ids, rand.Reader) - assert.NoError(t, err) + _, shares, _, err := Create(tss.EC(), threshold, secret, ids, rand.Reader) + if err != nil { + t.Fatal(err) + } secret2, err2 := shares[:threshold-1].ReConstruct(tss.EC()) - assert.Error(t, err2) // not enough shares to satisfy the threshold - assert.Nil(t, secret2) + if err2 == nil { + t.Fatal("expected error") + } + if secret2 != nil { + t.Fatalf("expected nil, got %v", secret2) + } secret3, err3 := shares[:threshold].ReConstruct(tss.EC()) - assert.NoError(t, err3) - assert.NotZero(t, secret3) + if err3 != nil { + t.Fatal(err3) + } + if secret3 == nil { + t.Fatal("expected non-zero") + } secret4, err4 := shares[:num].ReConstruct(tss.EC()) - assert.NoError(t, err4) - assert.NotZero(t, secret4) + if err4 != nil { + t.Fatal(err4) + } + if secret4 == nil { + t.Fatal("expected non-zero") + } } diff --git a/tss-lib/crypto/vss/negative_test.go b/tss-lib/crypto/vss/negative_test.go new file mode 100644 index 0000000..495d5f5 --- /dev/null +++ b/tss-lib/crypto/vss/negative_test.go @@ -0,0 +1,116 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package vss + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestCreateThresholdTooHigh(t *testing.T) { + ec := tss.S256() + ids := []*big.Int{big.NewInt(1), big.NewInt(2)} + _, _, _, err := Create(ec, 5, big.NewInt(42), ids, rand.Reader) + if err == nil { + t.Fatal("expected error for threshold >= len(ids)") + } +} + +func TestCreateZeroSecret(t *testing.T) { + ec := tss.S256() + ids := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + _, _, _, err := Create(ec, 1, big.NewInt(0), ids, rand.Reader) + if err == nil { + t.Fatal("expected error for zero secret") + } +} + +func TestCreateNilIDs(t *testing.T) { + ec := tss.S256() + _, _, _, err := Create(ec, 1, big.NewInt(42), nil, rand.Reader) + if err == nil { + t.Fatal("expected error for nil ids") + } +} + +func TestCreateEmptyIDs(t *testing.T) { + ec := tss.S256() + _, _, _, err := Create(ec, 1, big.NewInt(42), []*big.Int{}, rand.Reader) + if err == nil { + t.Fatal("expected error for empty ids") + } +} + +func TestVerifyBadShare(t *testing.T) { + ec := tss.S256() + ids := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + vs, shares, _, err := Create(ec, 1, big.NewInt(42), ids, rand.Reader) + if err != nil { + t.Fatalf("Create: %v", err) + } + badShare := new(big.Int).Add(shares[0].Share, big.NewInt(1)) + badShareCopy := &Share{Threshold: shares[0].Threshold, ID: shares[0].ID, Share: badShare} + if ok := badShareCopy.Verify(ec, 1, vs); ok { + t.Fatal("corrupted share should fail verification") + } +} + +func TestReConstructNotEnoughShares(t *testing.T) { + ec := tss.S256() + // threshold=2 means 3 shares needed for reconstruction. + ids := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4)} + _, shares, _, err := Create(ec, 2, big.NewInt(42), ids, rand.Reader) + if err != nil { + t.Fatalf("Create: %v", err) + } + // Only pass 1 share — need 3 (threshold+1). + _, err = shares[:1].ReConstruct(ec) + if err == nil { + t.Fatal("expected error with insufficient shares") + } +} + +func TestVerifyWrongThreshold(t *testing.T) { + ec := tss.S256() + ids := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + vs, shares, _, err := Create(ec, 1, big.NewInt(42), ids, rand.Reader) + if err != nil { + t.Fatalf("Create: %v", err) + } + if ok := shares[0].Verify(ec, 0, vs); ok { + t.Fatal("wrong threshold should fail verification") + } +} + +func TestVerifyNilVs(t *testing.T) { + ec := tss.S256() + share := &Share{Threshold: 1, ID: big.NewInt(1), Share: big.NewInt(42)} + if ok := share.Verify(ec, 1, nil); ok { + t.Fatal("nil vs should fail verification") + } +} + +func TestCreateReconstructSuccess(t *testing.T) { + ec := tss.S256() + secret := big.NewInt(12345) + ids := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + _, shares, _, err := Create(ec, 1, secret, ids, rand.Reader) + if err != nil { + t.Fatalf("Create: %v", err) + } + reconstructed, err := shares[:2].ReConstruct(ec) + if err != nil { + t.Fatalf("ReConstruct: %v", err) + } + bigP := crypto.ScalarBaseMult(ec, secret) + bigR := crypto.ScalarBaseMult(ec, reconstructed) + if !bigP.Equals(bigR) { + t.Fatal("reconstructed secret doesn't match original") + } +} diff --git a/tss-lib/ecdsa/example_test.go b/tss-lib/ecdsa/example_test.go new file mode 100644 index 0000000..f82a9ac --- /dev/null +++ b/tss-lib/ecdsa/example_test.go @@ -0,0 +1,456 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +//go:build tssexamples +// +build tssexamples + +// Package ecdsa_test contains the canonical usage example for the +// tss-lib v3 ECDSA round function API. +// +// Run with: go test -tags tssexamples -v ./ecdsa/ -timeout 15m +package ecdsa_test + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "fmt" + "math/big" + "testing" + "time" + + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/resharing" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestECDSAKeygenSignReshare demonstrates the full ECDSA lifecycle: +// keygen → sign → reshare (with overlapping committees) → sign again. +// +// Old committee: [P0, P1, P2], threshold=1 (2-of-3) +// New committee: [P1, P2, P3], threshold=1 (2-of-3) +// P1 and P2 are in both committees. +// P0 drops out, P3 joins. +// The ECDSA public key is preserved across the reshare. +func TestECDSAKeygenSignReshare(t *testing.T) { + const threshold = 1 + ctx := context.Background() + + // ------------------------------------------------------------------ + // Phase 1: Paillier pre-parameters + // ------------------------------------------------------------------ + t.Log("generating Paillier pre-params for 4 parties...") + allPreParams := make([]keygen.LocalPreParams, 4) + for i := range allPreParams { + pp, err := keygen.GeneratePreParams(5 * time.Minute) + if err != nil { + t.Fatalf("GeneratePreParams[%d]: %v", i, err) + } + allPreParams[i] = *pp + } + t.Log("pre-params ready") + + // ------------------------------------------------------------------ + // Phase 2: Party IDs with separate copies per committee. + // SortPartyIDs assigns Index by position — shared PartyID objects + // would get their Index mutated by the second sort. + // ------------------------------------------------------------------ + allPIDs := tss.GenerateTestPartyIDs(4) + copyPID := func(src *tss.PartyID) *tss.PartyID { + return tss.NewPartyID(src.Id, src.Moniker, new(big.Int).SetBytes(src.Key)) + } + oldPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[0]), copyPID(allPIDs[1]), copyPID(allPIDs[2]), + }) + newPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[1]), copyPID(allPIDs[2]), copyPID(allPIDs[3]), + }) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + oldN := len(oldPIDs) + newN := len(newPIDs) + + // Map allPIDs index → pre-params for each party. + // oldPIDs uses allPIDs[0,1,2], newPIDs uses allPIDs[1,2,3]. + oldPreParams := []keygen.LocalPreParams{allPreParams[0], allPreParams[1], allPreParams[2]} + newPreParams := []keygen.LocalPreParams{allPreParams[1], allPreParams[2], allPreParams[3]} + + // ------------------------------------------------------------------ + // Phase 3: Keygen (4 rounds) + // ------------------------------------------------------------------ + oldSaves := ecdsaKeygen(t, ctx, oldN, threshold, oldPIDs, oldCtx, oldPreParams) + pubKey := oldSaves[0].ECDSAPub + t.Logf("keygen: ECDSAPub = (%x...)", pubKey.X().Bytes()[:8]) + + // ------------------------------------------------------------------ + // Phase 4: Sign with old committee + // ------------------------------------------------------------------ + msg1 := sha256.Sum256([]byte("pre-reshare message")) + sig1 := ecdsaSign(t, ctx, oldN, threshold, oldPIDs, oldCtx, oldSaves, new(big.Int).SetBytes(msg1[:])) + verifyECDSA(t, pubKey, msg1[:], sig1) + t.Log("pre-reshare signature verified") + + // ------------------------------------------------------------------ + // Phase 5: Reshare — old [P0,P1,P2] → new [P1,P2,P3] + // ------------------------------------------------------------------ + newSaves := ecdsaReshare(t, ctx, oldPIDs, newPIDs, oldCtx, newCtx, + oldSaves, oldPreParams, newPreParams, threshold, threshold) + + for i := 0; i < newN; i++ { + if !newSaves[i].ECDSAPub.Equals(pubKey) { + t.Fatalf("new party %d: pub key changed", i) + } + } + if oldSaves[0].Xi.Sign() != 0 { + t.Fatal("P0 Xi not zeroed") + } + t.Log("reshare complete, pub key preserved") + + // ------------------------------------------------------------------ + // Phase 6: Sign with new committee + // ------------------------------------------------------------------ + msg2 := sha256.Sum256([]byte("post-reshare message")) + sig2 := ecdsaSign(t, ctx, newN, threshold, newPIDs, newCtx, newSaves, new(big.Int).SetBytes(msg2[:])) + verifyECDSA(t, pubKey, msg2[:], sig2) + t.Log("post-reshare signature verified") +} + +// --- helpers --- + +// ecPoint is a point on an elliptic curve with X and Y coordinates. +type ecPoint interface { + X() *big.Int + Y() *big.Int +} + +func verifyECDSA(t *testing.T, pub ecPoint, msgHash []byte, sig *signing.SignatureData) { + t.Helper() + pk := &ecdsa.PublicKey{Curve: tss.S256(), X: pub.X(), Y: pub.Y()} + r := new(big.Int).SetBytes(sig.R) + s := new(big.Int).SetBytes(sig.S) + if !ecdsa.Verify(pk, msgHash, r, s) { + t.Fatal("ECDSA signature verification failed") + } +} + +func ecdsaKeygen(t *testing.T, ctx context.Context, n, threshold int, pIDs tss.SortedPartyIDs, peerCtx *tss.PeerContext, preParams []keygen.LocalPreParams) []keygen.LocalPartySaveData { + t.Helper() + + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(ctx, params, preParams[i]) + if err != nil { + t.Fatalf("keygen.Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + params.SetNoProofMod() + params.SetNoProofFac() + params.SetNoProofDLN() + out, err := keygen.Round2(ctx, states[i], r1) + if err != nil { + t.Fatalf("keygen.Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(ctx, states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("keygen.Round3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(ctx, states[i], r3) + if err != nil { + t.Fatalf("keygen.Round4[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves +} + +func ecdsaSign(t *testing.T, ctx context.Context, n, threshold int, pIDs tss.SortedPartyIDs, peerCtx *tss.PeerContext, saves []keygen.LocalPartySaveData, m *big.Int) *signing.SignatureData { + t.Helper() + + states := make([]*signing.SigningState, n) + r1p2p := make([][]*tss.Message, n) + r1bcast := make([]*tss.Message, n) + for i := range r1p2p { + r1p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := signing.SignRound1(params, saves[i], m, nil, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + states[i] = st + for _, msg := range out.Messages { + if msg.To == nil { + r1bcast[i] = msg + } else { + for _, to := range msg.To { + r1p2p[to.Index][i] = msg + } + } + } + } + + // Round 2 (MtA — P2P) + r2p2p := make([][]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := signing.SignRound2(ctx, states[i], r1p2p[i], r1bcast) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + + // Round 3 (broadcast) + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound3(ctx, states[i], r2p2p[i]) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + + // Rounds 4-9 + finalize (all broadcast) + r4 := bcastRound(t, n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound4(states[i], r3) + }, "Round4") + r5 := bcastRound(t, n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound5(states[i], r4) + }, "Round5") + r6 := bcastRound(t, n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound6(states[i]) + }, "Round6") + r7 := bcastRound(t, n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound7(states[i], r5, r6) + }, "Round7") + r8 := bcastRound(t, n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound8(states[i]) + }, "Round8") + r9 := bcastRound(t, n, states, func(i int) (*signing.SignRoundOutput, error) { + return signing.SignRound9(states[i], r7, r8) + }, "Round9") + + // Finalize + out, err := signing.SignFinalize(states[0], r9) + if err != nil { + t.Fatalf("SignFinalize: %v", err) + } + return out.Signature +} + +func bcastRound(t *testing.T, n int, states []*signing.SigningState, fn func(int) (*signing.SignRoundOutput, error), name string) []*tss.Message { + t.Helper() + msgs := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := fn(i) + if err != nil { + t.Fatalf("%s[%d]: %v", name, i, err) + } + msgs[i] = out.Messages[0] + } + return msgs +} + +func ecdsaReshare(t *testing.T, ctx context.Context, oldPIDs, newPIDs tss.SortedPartyIDs, oldCtx, newCtx *tss.PeerContext, oldSaves []keygen.LocalPartySaveData, oldPreParams, newPreParams []keygen.LocalPreParams, oldT, newT int) []keygen.LocalPartySaveData { + t.Helper() + + oldN := len(oldPIDs) + newN := len(newPIDs) + + type partyRole struct { + pid *tss.PartyID + oldIdx int + newIdx int + } + seen := make(map[string]*partyRole) + var allParties []*partyRole + for i, pid := range oldPIDs { + key := fmt.Sprintf("%x", pid.Key) + pr := &partyRole{pid: pid, oldIdx: i, newIdx: -1} + seen[key] = pr + allParties = append(allParties, pr) + } + for i, pid := range newPIDs { + key := fmt.Sprintf("%x", pid.Key) + if pr, ok := seen[key]; ok { + pr.newIdx = i + } else { + pr := &partyRole{pid: pid, oldIdx: -1, newIdx: i} + seen[key] = pr + allParties = append(allParties, pr) + } + } + + type stateEntry struct { + state *resharing.ReshareState + role *partyRole + } + entries := make([]stateEntry, len(allParties)) + + // --- Round 1 --- + r1Msgs := make([]*tss.Message, oldN) + for idx, pr := range allParties { + params := tss.NewReSharingParameters( + tss.S256(), oldCtx, newCtx, pr.pid, oldN, oldT, newN, newT) + params.SetNoProofMod() + params.SetNoProofFac() + params.SetNoProofDLN() + var key keygen.LocalPartySaveData + var pp keygen.LocalPreParams + if pr.oldIdx >= 0 { + key = oldSaves[pr.oldIdx] + } else { + key = keygen.NewLocalPartySaveData(oldN) + } + if pr.newIdx >= 0 { + pp = newPreParams[pr.newIdx] + } + st, out, err := resharing.ReshareRound1(params, key, pp) + if err != nil { + t.Fatalf("ReshareRound1[%s]: %v", pr.pid.Id, err) + } + entries[idx] = stateEntry{state: st, role: pr} + if pr.oldIdx >= 0 && len(out.Messages) > 0 { + r1Msgs[pr.oldIdx] = out.Messages[0] + } + } + + // --- Round 2 --- + r2Msg1s := make([]*tss.Message, newN) + r2Msg2s := make([]*tss.Message, newN) + for idx := range entries { + pr := entries[idx].role + out, err := resharing.ReshareRound2(entries[idx].state, r1Msgs) + if err != nil { + t.Fatalf("ReshareRound2[%s]: %v", pr.pid.Id, err) + } + if pr.newIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound2Message1: + r2Msg1s[pr.newIdx] = msg + case *resharing.DGRound2Message2: + r2Msg2s[pr.newIdx] = msg + } + } + } + } + + // --- Round 3 --- + r3P2P := make([][]*tss.Message, newN) + r3Bcast := make([]*tss.Message, oldN) + for i := range r3P2P { + r3P2P[i] = make([]*tss.Message, oldN) + } + for idx := range entries { + pr := entries[idx].role + out, err := resharing.ReshareRound3(entries[idx].state, r2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3[%s]: %v", pr.pid.Id, err) + } + if pr.oldIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound3Message2: + r3Bcast[pr.oldIdx] = msg + case *resharing.DGRound3Message1: + for _, to := range msg.To { + r3P2P[to.Index][pr.oldIdx] = msg + } + } + } + } + } + + // --- Round 4 --- + r4P2P := make([][]*tss.Message, newN) + r4Bcast := make([]*tss.Message, newN) + for i := range r4P2P { + r4P2P[i] = make([]*tss.Message, newN) + } + for idx := range entries { + pr := entries[idx].role + var myR3P2P []*tss.Message + if pr.newIdx >= 0 { + myR3P2P = r3P2P[pr.newIdx] + } + out, err := resharing.ReshareRound4(ctx, entries[idx].state, r2Msg1s, myR3P2P, r3Bcast) + if err != nil { + t.Fatalf("ReshareRound4[%s]: %v", pr.pid.Id, err) + } + if pr.newIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound4Message1: + for _, to := range msg.To { + r4P2P[to.Index][pr.newIdx] = msg + } + case *resharing.DGRound4Message2: + r4Bcast[pr.newIdx] = msg + } + } + } + } + + // --- Round 5 --- + newSaves := make([]keygen.LocalPartySaveData, newN) + for idx := range entries { + pr := entries[idx].role + var myR4P2P []*tss.Message + if pr.newIdx >= 0 { + myR4P2P = r4P2P[pr.newIdx] + } + out, err := resharing.ReshareRound5(entries[idx].state, myR4P2P, r4Bcast) + if err != nil { + t.Fatalf("ReshareRound5[%s]: %v", pr.pid.Id, err) + } + if pr.newIdx >= 0 { + newSaves[pr.newIdx] = *out.Save + } + } + + return newSaves +} diff --git a/tss-lib/ecdsa/keygen/dln_verifier.go b/tss-lib/ecdsa/keygen/dln_verifier.go index 6891a60..2b368af 100644 --- a/tss-lib/ecdsa/keygen/dln_verifier.go +++ b/tss-lib/ecdsa/keygen/dln_verifier.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen @@ -10,64 +9,35 @@ import ( "errors" "math/big" - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" ) +// DlnProofVerifier runs DLN proof verification concurrently with +// bounded parallelism. type DlnProofVerifier struct { semaphore chan interface{} } -type message interface { - UnmarshalDLNProof1() (*dlnproof.Proof, error) - UnmarshalDLNProof2() (*dlnproof.Proof, error) -} - +// NewDlnProofVerifier creates a verifier with the given concurrency. func NewDlnProofVerifier(concurrency int) *DlnProofVerifier { if concurrency == 0 { - panic(errors.New("NewDlnProofverifier: concurrency level must not be zero")) + panic(errors.New("NewDlnProofVerifier: concurrency level must not be zero")) } - - semaphore := make(chan interface{}, concurrency) - return &DlnProofVerifier{ - semaphore: semaphore, + semaphore: make(chan interface{}, concurrency), } } -func (dpv *DlnProofVerifier) VerifyDLNProof1( - m message, - h1, h2, n *big.Int, - onDone func(bool), -) { +// VerifyDLNProof verifies a DLN proof with bounded concurrency. +// The proof may be nil (SNARK mode), in which case onDone(false). +func (dpv *DlnProofVerifier) VerifyDLNProof(proof *dlnproof.Proof, Session []byte, h1, h2, n *big.Int, onDone func(bool)) { dpv.semaphore <- struct{}{} go func() { defer func() { <-dpv.semaphore }() - - dlnProof, err := m.UnmarshalDLNProof1() - if err != nil { + if proof == nil { onDone(false) return } - - onDone(dlnProof.Verify(h1, h2, n)) - }() -} - -func (dpv *DlnProofVerifier) VerifyDLNProof2( - m message, - h1, h2, n *big.Int, - onDone func(bool), -) { - dpv.semaphore <- struct{}{} - go func() { - defer func() { <-dpv.semaphore }() - - dlnProof, err := m.UnmarshalDLNProof2() - if err != nil { - onDone(false) - return - } - - onDone(dlnProof.Verify(h1, h2, n)) + onDone(proof.Verify(Session, h1, h2, n)) }() } diff --git a/tss-lib/ecdsa/keygen/dln_verifier_test.go b/tss-lib/ecdsa/keygen/dln_verifier_test.go index 0ba4b2e..5022f50 100644 --- a/tss-lib/ecdsa/keygen/dln_verifier_test.go +++ b/tss-lib/ecdsa/keygen/dln_verifier_test.go @@ -1,244 +1,476 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen import ( + "context" "crypto/rand" "math/big" + "reflect" "runtime" + "sync" + "sync/atomic" "testing" + "time" - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" ) -func BenchmarkDlnProof_Verify(b *testing.B) { - localPartySaveData, _, err := LoadKeygenTestFixtures(1) - if err != nil { - b.Fatal(err) - } - - params := localPartySaveData[0].LocalPreParams +// dlnTestParams holds a set of DLN proof parameters generated from real +// safe primes. Creating these is slow (~seconds) so tests that need them +// should call generateDLNTestParams once and reuse the result. +type dlnTestParams struct { + H1, H2 *big.Int + Alpha *big.Int // discrete log: H2 = H1^Alpha mod N + Beta *big.Int // modular inverse of Alpha mod p*q + P, Q *big.Int // Sophie Germain primes + N *big.Int // N = (2P+1)(2Q+1) + Session []byte +} - proof := dlnproof.NewDLNProof( - params.H1i, - params.H2i, - params.Alpha, - params.P, - params.Q, - params.NTildei, - rand.Reader, - ) +// generateDLNTestParams generates proper DLN proof parameters at runtime +// using safe primes, mirroring the logic in GeneratePreParamsWithContextAndRandom. +func generateDLNTestParams(t *testing.T) *dlnTestParams { + t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() - b.ResetTimer() - for n := 0; n < b.N; n++ { - proof.Verify(params.H1i, params.H2i, params.NTildei) + concurrency := runtime.NumCPU() + if concurrency < 1 { + concurrency = 1 } -} -func BenchmarkDlnVerifier_VerifyProof1(b *testing.B) { - preParams, proof := prepareProofB(b) - message := &KGRound1Message{ - Dlnproof_1: proof, + sgps, err := common.GetRandomSafePrimesConcurrent(ctx, 1024, 2, concurrency, rand.Reader) + if err != nil { + t.Fatalf("safe prime generation failed"+": %v", err) } - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) + p := sgps[0].Prime() + q := sgps[1].Prime() + safeP := sgps[0].SafePrime() + safeQ := sgps[1].SafePrime() + N := new(big.Int).Mul(safeP, safeQ) - b.ResetTimer() - for n := 0; n < b.N; n++ { - resultChan := make(chan bool) - verifier.VerifyDLNProof1(message, preParams.H1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result - }) - <-resultChan + modN := common.ModInt(N) + pMulQ := new(big.Int).Mul(p, q) + modPQ := common.ModInt(pMulQ) + + f := common.GetRandomPositiveRelativelyPrimeInt(rand.Reader, N) + h1 := modN.Mul(f, f) + + alpha := common.GetRandomPositiveRelativelyPrimeInt(rand.Reader, N) + alphaModPQ := new(big.Int).Mod(alpha, pMulQ) + beta := modPQ.ModInverse(alphaModPQ) + if beta == nil { + t.Fatal("alpha modular inverse failed") } -} -func BenchmarkDlnVerifier_VerifyProof2(b *testing.B) { - preParams, proof := prepareProofB(b) - message := &KGRound1Message{ - Dlnproof_2: proof, + h2 := modN.Exp(h1, alpha) + + return &dlnTestParams{ + H1: h1, + H2: h2, + Alpha: alphaModPQ, + Beta: beta, + P: p, + Q: q, + N: N, + Session: []byte("dln-verifier-test"), } +} - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) +// TestNewDlnProofVerifierZeroConcurrencyPanics verifies that constructing a +// DlnProofVerifier with concurrency=0 panics, as documented. +func TestNewDlnProofVerifierZeroConcurrencyPanics(t *testing.T) { + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("concurrency=0 must panic") + } + }() + NewDlnProofVerifier(0) + }() +} - b.ResetTimer() - for n := 0; n < b.N; n++ { - resultChan := make(chan bool) - verifier.VerifyDLNProof2(message, preParams.H1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result - }) - <-resultChan +// TestNewDlnProofVerifierValidConcurrency verifies that concurrency values +// 1 and greater succeed without panic. +func TestNewDlnProofVerifierValidConcurrency(t *testing.T) { + for _, c := range []int{1, 2, 4, 128} { + dpv := NewDlnProofVerifier(c) + if dpv == nil { + t.Fatalf("concurrency=%d should create valid verifier", c) + } } } -func TestVerifyDLNProof1_Success(t *testing.T) { - preParams, proof := prepareProofT(t) - message := &KGRound1Message{ - Dlnproof_1: proof, +// TestVerifyDLNProofSuccess creates a real DLN proof from safe-prime +// parameters and verifies that VerifyDLNProof calls onDone(true). +func TestVerifyDLNProofSuccess(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") } - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) - - resultChan := make(chan bool) - - verifier.VerifyDLNProof1(message, preParams.H1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result + dpv := NewDlnProofVerifier(1) + var result atomic.Bool + var wg sync.WaitGroup + wg.Add(1) + dpv.VerifyDLNProof(proof, params.Session, params.H1, params.H2, params.N, func(ok bool) { + result.Store(ok) + wg.Done() }) - - success := <-resultChan - if !success { - t.Fatal("expected positive verification") + wg.Wait() + if !result.Load() { + t.Fatal("valid proof must pass verification") } } -func TestVerifyDLNProof1_MalformedMessage(t *testing.T) { - preParams, proof := prepareProofT(t) - message := &KGRound1Message{ - Dlnproof_1: proof[:len(proof)-1], // truncate +// TestVerifyDLNProofIncorrectH1 creates a valid proof then verifies with a +// tampered H1 value, expecting onDone(false). +func TestVerifyDLNProofIncorrectH1(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") } - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) - - resultChan := make(chan bool) - - verifier.VerifyDLNProof1(message, preParams.H1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result + // Tamper: H1 + 2 (still odd, still in range, but wrong) + badH1 := new(big.Int).Add(params.H1, big.NewInt(2)) + + dpv := NewDlnProofVerifier(1) + var result atomic.Bool + result.Store(true) // pre-set to true to detect false negative + var wg sync.WaitGroup + wg.Add(1) + dpv.VerifyDLNProof(proof, params.Session, badH1, params.H2, params.N, func(ok bool) { + result.Store(ok) + wg.Done() }) - - success := <-resultChan - if success { - t.Fatal("expected negative verification") + wg.Wait() + if result.Load() { + t.Fatal("tampered H1 must cause verification failure") } } -func TestVerifyDLNProof1_IncorrectProof(t *testing.T) { - preParams, proof := prepareProofT(t) - message := &KGRound1Message{ - Dlnproof_1: proof, +// TestVerifyDLNProofIncorrectH2 creates a valid proof then verifies with a +// tampered H2 value, expecting onDone(false). +func TestVerifyDLNProofIncorrectH2(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") } - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) - - resultChan := make(chan bool) - - wrongH1i := preParams.H1i.Sub(preParams.H1i, big.NewInt(1)) - verifier.VerifyDLNProof1(message, wrongH1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result + // Tamper: H2 + 2 + badH2 := new(big.Int).Add(params.H2, big.NewInt(2)) + + dpv := NewDlnProofVerifier(1) + var result atomic.Bool + result.Store(true) + var wg sync.WaitGroup + wg.Add(1) + dpv.VerifyDLNProof(proof, params.Session, params.H1, badH2, params.N, func(ok bool) { + result.Store(ok) + wg.Done() }) - - success := <-resultChan - if success { - t.Fatal("expected negative verification") + wg.Wait() + if result.Load() { + t.Fatal("tampered H2 must cause verification failure") } } -func TestVerifyDLNProof2_Success(t *testing.T) { - preParams, proof := prepareProofT(t) - message := &KGRound1Message{ - Dlnproof_2: proof, +// TestVerifyDLNProofWrongSession creates a proof with one session ID and +// verifies with a different one, expecting onDone(false). This exercises +// the SSID domain-separation fork (SHA512_256i_TAGGED with Session). +func TestVerifyDLNProofWrongSession(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") } - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) - - resultChan := make(chan bool) + wrongSession := []byte("wrong-session-id") - verifier.VerifyDLNProof2(message, preParams.H1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result + dpv := NewDlnProofVerifier(1) + var result atomic.Bool + result.Store(true) + var wg sync.WaitGroup + wg.Add(1) + dpv.VerifyDLNProof(proof, wrongSession, params.H1, params.H2, params.N, func(ok bool) { + result.Store(ok) + wg.Done() }) - - success := <-resultChan - if !success { - t.Fatal("expected positive verification") + wg.Wait() + if result.Load() { + t.Fatal("wrong session must cause verification failure") } } -func TestVerifyDLNProof2_MalformedMessage(t *testing.T) { - preParams, proof := prepareProofT(t) - message := &KGRound1Message{ - Dlnproof_2: proof[:len(proof)-1], // truncate +// TestVerifyDLNProofNilProof passes a nil proof pointer and verifies that +// onDone(false) is called (SNARK mode path). +func TestVerifyDLNProofNilProof(t *testing.T) { + dpv := NewDlnProofVerifier(1) + var result atomic.Bool + result.Store(true) + var wg sync.WaitGroup + wg.Add(1) + dpv.VerifyDLNProof(nil, []byte("session"), big.NewInt(3), big.NewInt(5), big.NewInt(15), func(ok bool) { + result.Store(ok) + wg.Done() + }) + wg.Wait() + if result.Load() { + t.Fatal("nil proof must call onDone(false)") } +} - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) +// TestVerifyDLNProofNilProofCallbackInvoked ensures that with a nil proof the +// callback is always invoked exactly once (no deadlock, no double-call). +func TestVerifyDLNProofNilProofCallbackInvoked(t *testing.T) { + dpv := NewDlnProofVerifier(2) + var count atomic.Int32 + var wg sync.WaitGroup + + const iterations = 10 + wg.Add(iterations) + for i := 0; i < iterations; i++ { + dpv.VerifyDLNProof(nil, []byte("s"), big.NewInt(3), big.NewInt(5), big.NewInt(15), func(ok bool) { + if ok { + t.Fatal("expected false") + } + count.Add(1) + wg.Done() + }) + } + wg.Wait() + if !reflect.DeepEqual(int32(iterations), count.Load()) { + t.Fatalf("callback must be invoked exactly once per call") + } +} - resultChan := make(chan bool) +// TestVerifyDLNProofConcurrencyBound launches more verifications than the +// concurrency limit and verifies that all complete successfully. This +// exercises the semaphore: with concurrency=2 and 20 verifications, the +// goroutines must queue on the semaphore. +func TestVerifyDLNProofConcurrencyBound(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") + } - verifier.VerifyDLNProof2(message, preParams.H1i, preParams.H2i, preParams.NTildei, func(result bool) { - resultChan <- result - }) + const concurrency = 2 + const numVerifications = 20 + + dpv := NewDlnProofVerifier(concurrency) + var successCount atomic.Int32 + var failCount atomic.Int32 + var wg sync.WaitGroup + wg.Add(numVerifications) + + for i := 0; i < numVerifications; i++ { + dpv.VerifyDLNProof(proof, params.Session, params.H1, params.H2, params.N, func(ok bool) { + if ok { + successCount.Add(1) + } else { + failCount.Add(1) + } + wg.Done() + }) + } - success := <-resultChan - if success { - t.Fatal("expected negative verification") + wg.Wait() + if !reflect.DeepEqual(int32(numVerifications), successCount.Load()) { + t.Fatalf("all %d verifications must succeed", numVerifications) + } + if !reflect.DeepEqual(int32(0), failCount.Load()) { + t.Fatalf("no verifications should fail") } } -func TestVerifyDLNProof2_IncorrectProof(t *testing.T) { - preParams, proof := prepareProofT(t) - message := &KGRound1Message{ - Dlnproof_2: proof, +// TestVerifyDLNProofConcurrencyBoundMixed launches a mix of valid and nil +// proofs beyond the concurrency limit to verify that the semaphore properly +// serializes work and all callbacks fire correctly. +func TestVerifyDLNProofConcurrencyBoundMixed(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") } - verifier := NewDlnProofVerifier(runtime.GOMAXPROCS(0)) - - resultChan := make(chan bool) - - wrongH2i := preParams.H2i.Add(preParams.H2i, big.NewInt(1)) - verifier.VerifyDLNProof2(message, preParams.H1i, wrongH2i, preParams.NTildei, func(result bool) { - resultChan <- result - }) + const concurrency = 3 + const numValid = 10 + const numNil = 10 + const total = numValid + numNil + + dpv := NewDlnProofVerifier(concurrency) + var successCount atomic.Int32 + var failCount atomic.Int32 + var wg sync.WaitGroup + wg.Add(total) + + // Interleave valid and nil proofs. + for i := 0; i < total; i++ { + var p *dlnproof.Proof + if i%2 == 0 { + p = proof + } + dpv.VerifyDLNProof(p, params.Session, params.H1, params.H2, params.N, func(ok bool) { + if ok { + successCount.Add(1) + } else { + failCount.Add(1) + } + wg.Done() + }) + } - success := <-resultChan - if success { - t.Fatal("expected negative verification") + wg.Wait() + if !reflect.DeepEqual(int32(numValid), successCount.Load()) { + t.Fatalf("valid proofs must succeed") + } + if !reflect.DeepEqual(int32(numNil), failCount.Load()) { + t.Fatalf("nil proofs must fail") } } -func prepareProofT(t *testing.T) (*LocalPreParams, [][]byte) { - preParams, serialized, err := prepareProof() - if err != nil { - t.Fatal(err) - } +// TestVerifyDLNProofSemaphoreReleasedOnNilProof verifies that the semaphore +// slot is released even when the proof is nil. If it were not released, +// subsequent verifications would deadlock. +func TestVerifyDLNProofSemaphoreReleasedOnNilProof(t *testing.T) { + // concurrency=1: if the semaphore is not released after nil proof, + // the second call will block forever. + dpv := NewDlnProofVerifier(1) + + done := make(chan struct{}) + go func() { + var wg sync.WaitGroup + // First: nil proof + wg.Add(1) + dpv.VerifyDLNProof(nil, nil, nil, nil, nil, func(bool) { + wg.Done() + }) + wg.Wait() - return preParams, serialized + // Second: also nil — should not deadlock + wg.Add(1) + dpv.VerifyDLNProof(nil, nil, nil, nil, nil, func(bool) { + wg.Done() + }) + wg.Wait() + close(done) + }() + + select { + case <-done: + // success + case <-time.After(5 * time.Second): + t.Fatal("deadlock: semaphore not released after nil proof") + } } -func prepareProofB(b *testing.B) (*LocalPreParams, [][]byte) { - preParams, serialized, err := prepareProof() - if err != nil { - b.Fatal(err) +// TestVerifyDLNProofSwappedH1H2 verifies that swapping H1 and H2 at +// verification time causes failure. The proof is for (H1, H2) but we +// verify with (H2, H1). +func TestVerifyDLNProofSwappedH1H2(t *testing.T) { + params := generateDLNTestParams(t) + proof := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, + rand.Reader, + ) + if proof == nil { + t.Fatal("expected non-nil") } - return preParams, serialized -} - -func prepareProof() (*LocalPreParams, [][]byte, error) { - localPartySaveData, _, err := LoadKeygenTestFixtures(1) - if err != nil { - return nil, [][]byte{}, err + dpv := NewDlnProofVerifier(1) + var result atomic.Bool + result.Store(true) + var wg sync.WaitGroup + wg.Add(1) + // Swap H1 and H2 + dpv.VerifyDLNProof(proof, params.Session, params.H2, params.H1, params.N, func(ok bool) { + result.Store(ok) + wg.Done() + }) + wg.Wait() + if result.Load() { + t.Fatal("swapped H1/H2 must cause verification failure") } +} - preParams := localPartySaveData[0].LocalPreParams +// TestVerifyDLNProofBothProofDirections mirrors the Round 1 pattern where +// two DLN proofs are created: one for (H1, H2, Alpha) and one for +// (H2, H1, Beta). Both must verify with the correct parameters. +func TestVerifyDLNProofBothProofDirections(t *testing.T) { + params := generateDLNTestParams(t) - proof := dlnproof.NewDLNProof( - preParams.H1i, - preParams.H2i, - preParams.Alpha, - preParams.P, - preParams.Q, - preParams.NTildei, + // DLNProof1: proves knowledge of Alpha such that H2 = H1^Alpha mod N + proof1 := dlnproof.NewDLNProof( + params.Session, params.H1, params.H2, + params.Alpha, params.P, params.Q, params.N, rand.Reader, ) - - serialized, err := proof.Serialize() - if err != nil { - if err != nil { - return nil, [][]byte{}, err - } + // DLNProof2: proves knowledge of Beta such that H1 = H2^Beta mod N + proof2 := dlnproof.NewDLNProof( + params.Session, params.H2, params.H1, + params.Beta, params.P, params.Q, params.N, + rand.Reader, + ) + if proof1 == nil { + t.Fatal("expected non-nil") + } + if proof2 == nil { + t.Fatal("expected non-nil") } - return &preParams, serialized, nil + dpv := NewDlnProofVerifier(2) + + var result1, result2 atomic.Bool + var wg sync.WaitGroup + wg.Add(2) + dpv.VerifyDLNProof(proof1, params.Session, params.H1, params.H2, params.N, func(ok bool) { + result1.Store(ok) + wg.Done() + }) + dpv.VerifyDLNProof(proof2, params.Session, params.H2, params.H1, params.N, func(ok bool) { + result2.Store(ok) + wg.Done() + }) + wg.Wait() + if !result1.Load() { + t.Fatal("proof1 (H1->H2, Alpha) must verify") + } + if !result2.Load() { + t.Fatal("proof2 (H2->H1, Beta) must verify") + } } diff --git a/tss-lib/ecdsa/keygen/ecdsa-keygen.pb.go b/tss-lib/ecdsa/keygen/ecdsa-keygen.pb.go deleted file mode 100644 index 5029072..0000000 --- a/tss-lib/ecdsa/keygen/ecdsa-keygen.pb.go +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v3.20.3 -// source: protob/ecdsa-keygen.proto - -package keygen - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Represents a BROADCAST message sent during Round 1 of the ECDSA TSS keygen protocol. -type KGRound1Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` - PaillierN []byte `protobuf:"bytes,2,opt,name=paillier_n,json=paillierN,proto3" json:"paillier_n,omitempty"` - NTilde []byte `protobuf:"bytes,3,opt,name=n_tilde,json=nTilde,proto3" json:"n_tilde,omitempty"` - H1 []byte `protobuf:"bytes,4,opt,name=h1,proto3" json:"h1,omitempty"` - H2 []byte `protobuf:"bytes,5,opt,name=h2,proto3" json:"h2,omitempty"` - Dlnproof_1 [][]byte `protobuf:"bytes,6,rep,name=dlnproof_1,json=dlnproof1,proto3" json:"dlnproof_1,omitempty"` - Dlnproof_2 [][]byte `protobuf:"bytes,7,rep,name=dlnproof_2,json=dlnproof2,proto3" json:"dlnproof_2,omitempty"` -} - -func (x *KGRound1Message) Reset() { - *x = KGRound1Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound1Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound1Message) ProtoMessage() {} - -func (x *KGRound1Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound1Message.ProtoReflect.Descriptor instead. -func (*KGRound1Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_keygen_proto_rawDescGZIP(), []int{0} -} - -func (x *KGRound1Message) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -func (x *KGRound1Message) GetPaillierN() []byte { - if x != nil { - return x.PaillierN - } - return nil -} - -func (x *KGRound1Message) GetNTilde() []byte { - if x != nil { - return x.NTilde - } - return nil -} - -func (x *KGRound1Message) GetH1() []byte { - if x != nil { - return x.H1 - } - return nil -} - -func (x *KGRound1Message) GetH2() []byte { - if x != nil { - return x.H2 - } - return nil -} - -func (x *KGRound1Message) GetDlnproof_1() [][]byte { - if x != nil { - return x.Dlnproof_1 - } - return nil -} - -func (x *KGRound1Message) GetDlnproof_2() [][]byte { - if x != nil { - return x.Dlnproof_2 - } - return nil -} - -// Represents a P2P message sent to each party during Round 2 of the ECDSA TSS keygen protocol. -type KGRound2Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Share []byte `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"` - FacProof [][]byte `protobuf:"bytes,2,rep,name=facProof,proto3" json:"facProof,omitempty"` -} - -func (x *KGRound2Message1) Reset() { - *x = KGRound2Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound2Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound2Message1) ProtoMessage() {} - -func (x *KGRound2Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound2Message1.ProtoReflect.Descriptor instead. -func (*KGRound2Message1) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_keygen_proto_rawDescGZIP(), []int{1} -} - -func (x *KGRound2Message1) GetShare() []byte { - if x != nil { - return x.Share - } - return nil -} - -func (x *KGRound2Message1) GetFacProof() [][]byte { - if x != nil { - return x.FacProof - } - return nil -} - -// Represents a BROADCAST message sent to each party during Round 2 of the ECDSA TSS keygen protocol. -type KGRound2Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeCommitment [][]byte `protobuf:"bytes,1,rep,name=de_commitment,json=deCommitment,proto3" json:"de_commitment,omitempty"` - ModProof [][]byte `protobuf:"bytes,2,rep,name=modProof,proto3" json:"modProof,omitempty"` -} - -func (x *KGRound2Message2) Reset() { - *x = KGRound2Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound2Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound2Message2) ProtoMessage() {} - -func (x *KGRound2Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound2Message2.ProtoReflect.Descriptor instead. -func (*KGRound2Message2) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_keygen_proto_rawDescGZIP(), []int{2} -} - -func (x *KGRound2Message2) GetDeCommitment() [][]byte { - if x != nil { - return x.DeCommitment - } - return nil -} - -func (x *KGRound2Message2) GetModProof() [][]byte { - if x != nil { - return x.ModProof - } - return nil -} - -// Represents a BROADCAST message sent to each party during Round 3 of the ECDSA TSS keygen protocol. -type KGRound3Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PaillierProof [][]byte `protobuf:"bytes,1,rep,name=paillier_proof,json=paillierProof,proto3" json:"paillier_proof,omitempty"` -} - -func (x *KGRound3Message) Reset() { - *x = KGRound3Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound3Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound3Message) ProtoMessage() {} - -func (x *KGRound3Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_keygen_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound3Message.ProtoReflect.Descriptor instead. -func (*KGRound3Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_keygen_proto_rawDescGZIP(), []int{3} -} - -func (x *KGRound3Message) GetPaillierProof() [][]byte { - if x != nil { - return x.PaillierProof - } - return nil -} - -var File_protob_ecdsa_keygen_proto protoreflect.FileDescriptor - -var file_protob_ecdsa_keygen_proto_rawDesc = []byte{ - 0x0a, 0x19, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x6b, - 0x65, 0x79, 0x67, 0x65, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x62, 0x69, 0x6e, - 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x63, 0x64, 0x73, - 0x61, 0x2e, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x22, 0xc7, 0x01, 0x0a, 0x0f, 0x4b, 0x47, 0x52, - 0x6f, 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65, 0x72, 0x4e, 0x12, 0x17, 0x0a, 0x07, 0x6e, - 0x5f, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x54, - 0x69, 0x6c, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x02, 0x68, 0x31, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x02, 0x68, 0x32, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x5f, 0x31, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x31, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, - 0x32, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x32, 0x22, 0x44, 0x0a, 0x10, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x66, 0x61, 0x63, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, - 0x66, 0x61, 0x63, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x53, 0x0a, 0x10, 0x4b, 0x47, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x12, 0x23, 0x0a, 0x0d, - 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x6f, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x38, 0x0a, - 0x0f, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, - 0x65, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x0e, 0x5a, 0x0c, 0x65, 0x63, 0x64, 0x73, 0x61, - 0x2f, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_protob_ecdsa_keygen_proto_rawDescOnce sync.Once - file_protob_ecdsa_keygen_proto_rawDescData = file_protob_ecdsa_keygen_proto_rawDesc -) - -func file_protob_ecdsa_keygen_proto_rawDescGZIP() []byte { - file_protob_ecdsa_keygen_proto_rawDescOnce.Do(func() { - file_protob_ecdsa_keygen_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_ecdsa_keygen_proto_rawDescData) - }) - return file_protob_ecdsa_keygen_proto_rawDescData -} - -var file_protob_ecdsa_keygen_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_protob_ecdsa_keygen_proto_goTypes = []interface{}{ - (*KGRound1Message)(nil), // 0: binance.tsslib.ecdsa.keygen.KGRound1Message - (*KGRound2Message1)(nil), // 1: binance.tsslib.ecdsa.keygen.KGRound2Message1 - (*KGRound2Message2)(nil), // 2: binance.tsslib.ecdsa.keygen.KGRound2Message2 - (*KGRound3Message)(nil), // 3: binance.tsslib.ecdsa.keygen.KGRound3Message -} -var file_protob_ecdsa_keygen_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_protob_ecdsa_keygen_proto_init() } -func file_protob_ecdsa_keygen_proto_init() { - if File_protob_ecdsa_keygen_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_ecdsa_keygen_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound1Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_keygen_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound2Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_keygen_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound2Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_keygen_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound3Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_ecdsa_keygen_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_ecdsa_keygen_proto_goTypes, - DependencyIndexes: file_protob_ecdsa_keygen_proto_depIdxs, - MessageInfos: file_protob_ecdsa_keygen_proto_msgTypes, - }.Build() - File_protob_ecdsa_keygen_proto = out.File - file_protob_ecdsa_keygen_proto_rawDesc = nil - file_protob_ecdsa_keygen_proto_goTypes = nil - file_protob_ecdsa_keygen_proto_depIdxs = nil -} diff --git a/tss-lib/ecdsa/keygen/local_party.go b/tss-lib/ecdsa/keygen/local_party.go deleted file mode 100644 index 6441963..0000000 --- a/tss-lib/ecdsa/keygen/local_party.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Implements Party -// Implements Stringer -var ( - _ tss.Party = (*LocalParty)(nil) - _ fmt.Stringer = (*LocalParty)(nil) -) - -type ( - LocalParty struct { - *tss.BaseParty - params *tss.Parameters - - temp localTempData - data LocalPartySaveData - - // outbound messaging - out chan<- tss.Message - end chan<- *LocalPartySaveData - } - - localMessageStore struct { - kgRound1Messages, - kgRound2Message1s, - kgRound2Message2s, - kgRound3Messages []tss.ParsedMessage - } - - localTempData struct { - localMessageStore - - // temp data (thrown away after keygen) - ui *big.Int // used for tests - KGCs []cmt.HashCommitment - vs vss.Vs - ssid []byte - ssidNonce *big.Int - shares vss.Shares - deCommitPolyG cmt.HashDeCommitment - } -) - -// Exported, used in `tss` client -func NewLocalParty( - params *tss.Parameters, - out chan<- tss.Message, - end chan<- *LocalPartySaveData, - optionalPreParams ...LocalPreParams, -) tss.Party { - partyCount := params.PartyCount() - data := NewLocalPartySaveData(partyCount) - // when `optionalPreParams` is provided we'll use the pre-computed primes instead of generating them from scratch - if 0 < len(optionalPreParams) { - if 1 < len(optionalPreParams) { - panic(errors.New("keygen.NewLocalParty expected 0 or 1 item in `optionalPreParams`")) - } - if !optionalPreParams[0].ValidateWithProof() { - panic(errors.New("`optionalPreParams` failed to validate; it might have been generated with an older version of tss-lib")) - } - data.LocalPreParams = optionalPreParams[0] - } - p := &LocalParty{ - BaseParty: new(tss.BaseParty), - params: params, - temp: localTempData{}, - data: data, - out: out, - end: end, - } - // msgs init - p.temp.kgRound1Messages = make([]tss.ParsedMessage, partyCount) - p.temp.kgRound2Message1s = make([]tss.ParsedMessage, partyCount) - p.temp.kgRound2Message2s = make([]tss.ParsedMessage, partyCount) - p.temp.kgRound3Messages = make([]tss.ParsedMessage, partyCount) - // temp data init - p.temp.KGCs = make([]cmt.HashCommitment, partyCount) - return p -} - -func (p *LocalParty) FirstRound() tss.Round { - return newRound1(p.params, &p.data, &p.temp, p.out, p.end) -} - -func (p *LocalParty) Start() *tss.Error { - return tss.BaseStart(p, TaskName) -} - -func (p *LocalParty) Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) { - return tss.BaseUpdate(p, msg, TaskName) -} - -func (p *LocalParty) UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (bool, *tss.Error) { - msg, err := tss.ParseWireMessage(wireBytes, from, isBroadcast) - if err != nil { - return false, p.WrapError(err) - } - return p.Update(msg) -} - -func (p *LocalParty) ValidateMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - if ok, err := p.BaseParty.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - // check that the message's "from index" will fit into the array - if maxFromIdx := p.params.PartyCount() - 1; maxFromIdx < msg.GetFrom().Index { - return false, p.WrapError(fmt.Errorf("received msg with a sender index too great (%d <= %d)", - p.params.PartyCount(), msg.GetFrom().Index), msg.GetFrom()) - } - return true, nil -} - -func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - // ValidateBasic is cheap; double-check the message here in case the public StoreMessage was called externally - if ok, err := p.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - fromPIdx := msg.GetFrom().Index - - // switch/case is necessary to store any messages beyond current round - // this does not handle message replays. we expect the caller to apply replay and spoofing protection. - switch msg.Content().(type) { - case *KGRound1Message: - p.temp.kgRound1Messages[fromPIdx] = msg - case *KGRound2Message1: - p.temp.kgRound2Message1s[fromPIdx] = msg - case *KGRound2Message2: - p.temp.kgRound2Message2s[fromPIdx] = msg - case *KGRound3Message: - p.temp.kgRound3Messages[fromPIdx] = msg - default: // unrecognised message, just ignore! - common.Logger.Warningf("unrecognised message ignored: %v", msg) - return false, nil - } - return true, nil -} - -// recovers a party's original index in the set of parties during keygen -func (save LocalPartySaveData) OriginalIndex() (int, error) { - index := -1 - ki := save.ShareID - for j, kj := range save.Ks { - if kj.Cmp(ki) != 0 { - continue - } - index = j - break - } - if index < 0 { - return -1, errors.New("a party index could not be recovered from Ks") - } - return index, nil -} - -func (p *LocalParty) PartyID() *tss.PartyID { - return p.params.PartyID() -} - -func (p *LocalParty) String() string { - return fmt.Sprintf("id: %s, %s", p.PartyID(), p.BaseParty.String()) -} diff --git a/tss-lib/ecdsa/keygen/local_party_test.go b/tss-lib/ecdsa/keygen/local_party_test.go deleted file mode 100644 index 8297911..0000000 --- a/tss-lib/ecdsa/keygen/local_party_test.go +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "crypto/ecdsa" - "crypto/rand" - "encoding/json" - "fmt" - "math/big" - "os" - "runtime" - "sync/atomic" - "testing" - - "github.com/ipfs/go-log" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - testParticipants = TestParticipants - testThreshold = TestThreshold -) - -func setUp(level string) { - if err := log.SetLogLevel("tss-lib", level); err != nil { - panic(err) - } -} - -func TestStartRound1Paillier(t *testing.T) { - setUp("debug") - - pIDs := tss.GenerateTestPartyIDs(1) - p2pCtx := tss.NewPeerContext(pIDs) - threshold := 1 - params := tss.NewParameters(tss.EC(), p2pCtx, pIDs[0], len(pIDs), threshold) - - fixtures, pIDs, err := LoadKeygenTestFixtures(testParticipants) - if err != nil { - common.Logger.Info("No test fixtures were found, so the safe primes will be generated from scratch. This may take a while...") - pIDs = tss.GenerateTestPartyIDs(testParticipants) - } - - var lp *LocalParty - out := make(chan tss.Message, len(pIDs)) - if 0 < len(fixtures) { - lp = NewLocalParty(params, out, nil, fixtures[0].LocalPreParams).(*LocalParty) - } else { - lp = NewLocalParty(params, out, nil).(*LocalParty) - } - if err := lp.Start(); err != nil { - assert.FailNow(t, err.Error()) - } - <-out - - // Paillier modulus 2048 (two 1024-bit primes) - // round up to 256, it was used to be flaky, sometimes comes back with 1 byte less - len1 := len(lp.data.PaillierSK.LambdaN.Bytes()) - len2 := len(lp.data.PaillierSK.PublicKey.N.Bytes()) - if len1%2 != 0 { - len1 = len1 + (256 - (len1 % 256)) - } - if len2%2 != 0 { - len2 = len2 + (256 - (len2 % 256)) - } - assert.Equal(t, 2048/8, len1) - assert.Equal(t, 2048/8, len2) -} - -func TestFinishAndSaveH1H2(t *testing.T) { - setUp("debug") - - pIDs := tss.GenerateTestPartyIDs(1) - p2pCtx := tss.NewPeerContext(pIDs) - threshold := 1 - params := tss.NewParameters(tss.EC(), p2pCtx, pIDs[0], len(pIDs), threshold) - - fixtures, pIDs, err := LoadKeygenTestFixtures(testParticipants) - if err != nil { - common.Logger.Info("No test fixtures were found, so the safe primes will be generated from scratch. This may take a while...") - pIDs = tss.GenerateTestPartyIDs(testParticipants) - } - - var lp *LocalParty - out := make(chan tss.Message, len(pIDs)) - if 0 < len(fixtures) { - lp = NewLocalParty(params, out, nil, fixtures[0].LocalPreParams).(*LocalParty) - } else { - lp = NewLocalParty(params, out, nil).(*LocalParty) - } - if err := lp.Start(); err != nil { - assert.FailNow(t, err.Error()) - } - - // RSA modulus 2048 (two 1024-bit primes) - // round up to 256 - len1 := len(lp.data.H1j[0].Bytes()) - len2 := len(lp.data.H2j[0].Bytes()) - len3 := len(lp.data.NTildej[0].Bytes()) - if len1%2 != 0 { - len1 = len1 + (256 - (len1 % 256)) - } - if len2%2 != 0 { - len2 = len2 + (256 - (len2 % 256)) - } - if len3%2 != 0 { - len3 = len3 + (256 - (len3 % 256)) - } - // 256 bytes = 2048 bits - assert.Equal(t, 256, len1, "h1 should be correct len") - assert.Equal(t, 256, len2, "h2 should be correct len") - assert.Equal(t, 256, len3, "n-tilde should be correct len") - assert.NotZero(t, lp.data.H1i, "h1 should be non-zero") - assert.NotZero(t, lp.data.H2i, "h2 should be non-zero") - assert.NotZero(t, lp.data.NTildei, "n-tilde should be non-zero") -} - -func TestBadMessageCulprits(t *testing.T) { - setUp("debug") - - pIDs := tss.GenerateTestPartyIDs(2) - p2pCtx := tss.NewPeerContext(pIDs) - params := tss.NewParameters(tss.S256(), p2pCtx, pIDs[0], len(pIDs), 1) - - fixtures, pIDs, err := LoadKeygenTestFixtures(testParticipants) - if err != nil { - common.Logger.Info("No test fixtures were found, so the safe primes will be generated from scratch. This may take a while...") - pIDs = tss.GenerateTestPartyIDs(testParticipants) - } - - var lp *LocalParty - out := make(chan tss.Message, len(pIDs)) - if 0 < len(fixtures) { - lp = NewLocalParty(params, out, nil, fixtures[0].LocalPreParams).(*LocalParty) - } else { - lp = NewLocalParty(params, out, nil).(*LocalParty) - } - if err := lp.Start(); err != nil { - assert.FailNow(t, err.Error()) - } - - badMsg, _ := NewKGRound1Message(pIDs[1], zero, &paillier.PublicKey{N: zero}, zero, zero, zero, new(dlnproof.Proof), new(dlnproof.Proof)) - ok, err2 := lp.Update(badMsg) - t.Log(err2) - assert.False(t, ok) - if !assert.Error(t, err2) { - return - } - assert.Equal(t, 1, len(err2.Culprits())) - assert.Equal(t, pIDs[1], err2.Culprits()[0]) - assert.Equal(t, - "task ecdsa-keygen, party {0,P[1]}, round 1, culprits [{1,2}]: message failed ValidateBasic: Type: binance.tsslib.ecdsa.keygen.KGRound1Message, From: {1,2}, To: all", - err2.Error()) -} - -func TestE2EConcurrentAndSaveFixtures(t *testing.T) { - setUp("info") - - // tss.SetCurve(elliptic.P256()) - - threshold := testThreshold - fixtures, pIDs, err := LoadKeygenTestFixtures(testParticipants) - if err != nil { - common.Logger.Info("No test fixtures were found, so the safe primes will be generated from scratch. This may take a while...") - pIDs = tss.GenerateTestPartyIDs(testParticipants) - } - - p2pCtx := tss.NewPeerContext(pIDs) - parties := make([]*LocalParty, 0, len(pIDs)) - - errCh := make(chan *tss.Error, len(pIDs)) - outCh := make(chan tss.Message, len(pIDs)) - endCh := make(chan *LocalPartySaveData, len(pIDs)) - - updater := test.SharedPartyUpdater - - startGR := runtime.NumGoroutine() - - // init the parties - for i := 0; i < len(pIDs); i++ { - var P *LocalParty - params := tss.NewParameters(tss.S256(), p2pCtx, pIDs[i], len(pIDs), threshold) - // do not use in untrusted setting - params.SetNoProofMod() - // do not use in untrusted setting - params.SetNoProofFac() - if i < len(fixtures) { - P = NewLocalParty(params, outCh, endCh, fixtures[i].LocalPreParams).(*LocalParty) - } else { - P = NewLocalParty(params, outCh, endCh).(*LocalParty) - } - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - // PHASE: keygen - var ended int32 -keygen: - for { - fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break keygen - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { // broadcast! - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { // point-to-point! - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - return - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case save := <-endCh: - // SAVE a test fixture file for this P (if it doesn't already exist) - // .. here comes a workaround to recover this party's index (it was removed from save data) - index, err := save.OriginalIndex() - assert.NoErrorf(t, err, "should not be an error getting a party's index from save data") - tryWriteTestFixtureFile(t, index, *save) - - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(pIDs)) { - t.Logf("Done. Received save data from %d participants", ended) - - // combine shares for each Pj to get u - u := new(big.Int) - for j, Pj := range parties { - pShares := make(vss.Shares, 0) - for _, P := range parties { - vssMsgs := P.temp.kgRound2Message1s - share := vssMsgs[j].Content().(*KGRound2Message1).Share - shareStruct := &vss.Share{ - Threshold: threshold, - ID: P.PartyID().KeyInt(), - Share: new(big.Int).SetBytes(share), - } - pShares = append(pShares, shareStruct) - } - uj, err := pShares[:threshold+1].ReConstruct(tss.S256()) - assert.NoError(t, err, "vss.ReConstruct should not throw error") - - // uG test: u*G[j] == V[0] - assert.Equal(t, uj, Pj.temp.ui) - uG := crypto.ScalarBaseMult(tss.EC(), uj) - assert.True(t, uG.Equals(Pj.temp.vs[0]), "ensure u*G[j] == V_0") - - // xj tests: BigXj == xj*G - xj := Pj.data.Xi - gXj := crypto.ScalarBaseMult(tss.EC(), xj) - BigXj := Pj.data.BigXj[j] - assert.True(t, BigXj.Equals(gXj), "ensure BigX_j == g^x_j") - - // fails if threshold cannot be satisfied (bad share) - { - badShares := pShares[:threshold] - badShares[len(badShares)-1].Share.Set(big.NewInt(0)) - uj, err := pShares[:threshold].ReConstruct(tss.S256()) - assert.NoError(t, err) - assert.NotEqual(t, parties[j].temp.ui, uj) - BigXjX, BigXjY := tss.EC().ScalarBaseMult(uj.Bytes()) - assert.NotEqual(t, BigXjX, Pj.temp.vs[0].X()) - assert.NotEqual(t, BigXjY, Pj.temp.vs[0].Y()) - } - u = new(big.Int).Add(u, uj) - } - - // build ecdsa key pair - pkX, pkY := save.ECDSAPub.X(), save.ECDSAPub.Y() - pk := ecdsa.PublicKey{ - Curve: tss.EC(), - X: pkX, - Y: pkY, - } - sk := ecdsa.PrivateKey{ - PublicKey: pk, - D: u, - } - // test pub key, should be on curve and match pkX, pkY - assert.True(t, sk.IsOnCurve(pkX, pkY), "public key must be on curve") - - // public key tests - assert.NotZero(t, u, "u should not be zero") - ourPkX, ourPkY := tss.EC().ScalarBaseMult(u.Bytes()) - assert.Equal(t, pkX, ourPkX, "pkX should match expected pk derived from u") - assert.Equal(t, pkY, ourPkY, "pkY should match expected pk derived from u") - t.Log("Public key tests done.") - - // make sure everyone has the same ECDSA public key - for _, Pj := range parties { - assert.Equal(t, pkX, Pj.data.ECDSAPub.X()) - assert.Equal(t, pkY, Pj.data.ECDSAPub.Y()) - } - t.Log("Public key distribution test done.") - - // test sign/verify - data := make([]byte, 32) - for i := range data { - data[i] = byte(i) - } - r, s, err := ecdsa.Sign(rand.Reader, &sk, data) - assert.NoError(t, err, "sign should not throw an error") - ok := ecdsa.Verify(&pk, data, r, s) - assert.True(t, ok, "signature should be ok") - t.Log("ECDSA signing test done.") - - t.Logf("Start goroutines: %d, End goroutines: %d", startGR, runtime.NumGoroutine()) - - break keygen - } - } - } -} - -func tryWriteTestFixtureFile(t *testing.T, index int, data LocalPartySaveData) { - fixtureFileName := makeTestFixtureFilePath(index) - - // fixture file does not already exist? - // if it does, we won't re-create it here - fi, err := os.Stat(fixtureFileName) - if !(err == nil && fi != nil && !fi.IsDir()) { - fd, err := os.OpenFile(fixtureFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - assert.NoErrorf(t, err, "unable to open fixture file %s for writing", fixtureFileName) - } - bz, err := json.Marshal(&data) - if err != nil { - t.Fatalf("unable to marshal save data for fixture file %s", fixtureFileName) - } - _, err = fd.Write(bz) - if err != nil { - t.Fatalf("unable to write to fixture file %s", fixtureFileName) - } - t.Logf("Saved a test fixture file for party %d: %s", index, fixtureFileName) - } else { - t.Logf("Fixture file already exists for party %d; not re-creating: %s", index, fixtureFileName) - } - // -} diff --git a/tss-lib/ecdsa/keygen/messages.go b/tss-lib/ecdsa/keygen/messages.go index 672f628..edcca89 100644 --- a/tss-lib/ecdsa/keygen/messages.go +++ b/tss-lib/ecdsa/keygen/messages.go @@ -1,218 +1,158 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen import ( - "github.com/hemilabs/x/tss-lib/v2/crypto/facproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/modproof" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -// These messages were generated from Protocol Buffers definitions into ecdsa-keygen.pb.go -// The following messages are registered on the Protocol Buffers "wire" - -var ( - // Ensure that keygen messages implement ValidateBasic - _ = []tss.MessageContent{ - (*KGRound1Message)(nil), - (*KGRound2Message1)(nil), - (*KGRound2Message2)(nil), - (*KGRound3Message)(nil), +// KGRound1Message is broadcast by each party in keygen round 1. +// Contains the commitment hash, Paillier public key, Pedersen +// parameters (NTilde, H1, H2) and optional DLN proofs. +type KGRound1Message struct { + Commitment *big.Int + PaillierPK *paillier.PublicKey + NTilde *big.Int + H1 *big.Int + H2 *big.Int + DLNProof1 *dlnproof.Proof // nil in on-chain SNARK mode + DLNProof2 *dlnproof.Proof // nil in on-chain SNARK mode +} + +// ValidateBasic checks that all required fields are non-nil and +// within expected bounds. +func (m *KGRound1Message) ValidateBasic() bool { + if m == nil { + return false } -) - -// ----- // - -func NewKGRound1Message( - from *tss.PartyID, - ct cmt.HashCommitment, - paillierPK *paillier.PublicKey, - nTildeI, h1I, h2I *big.Int, - dlnProof1, dlnProof2 *dlnproof.Proof, -) (tss.ParsedMessage, error) { - meta := tss.MessageRouting{ - From: from, - IsBroadcast: true, + if m.Commitment == nil || m.Commitment.Sign() == 0 { + return false } - dlnProof1Bz, err := dlnProof1.Serialize() - if err != nil { - return nil, err + if m.PaillierPK == nil || m.PaillierPK.N == nil || m.PaillierPK.N.Sign() == 0 { + return false } - dlnProof2Bz, err := dlnProof2.Serialize() - if err != nil { - return nil, err + if m.NTilde == nil || m.NTilde.Sign() == 0 { + return false } - content := &KGRound1Message{ - Commitment: ct.Bytes(), - PaillierN: paillierPK.N.Bytes(), - NTilde: nTildeI.Bytes(), - H1: h1I.Bytes(), - H2: h2I.Bytes(), - Dlnproof_1: dlnProof1Bz, - Dlnproof_2: dlnProof2Bz, + if m.H1 == nil || m.H1.Sign() == 0 { + return false } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg), nil -} - -func (m *KGRound1Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.GetCommitment()) && - common.NonEmptyBytes(m.GetPaillierN()) && - common.NonEmptyBytes(m.GetNTilde()) && - common.NonEmptyBytes(m.GetH1()) && - common.NonEmptyBytes(m.GetH2()) && - // expected len of dln proof = sizeof(int64) + len(alpha) + len(t) - common.NonEmptyMultiBytes(m.GetDlnproof_1(), 2+(dlnproof.Iterations*2)) && - common.NonEmptyMultiBytes(m.GetDlnproof_2(), 2+(dlnproof.Iterations*2)) -} - -func (m *KGRound1Message) UnmarshalCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetCommitment()) -} - -func (m *KGRound1Message) UnmarshalPaillierPK() *paillier.PublicKey { - return &paillier.PublicKey{N: new(big.Int).SetBytes(m.GetPaillierN())} -} - -func (m *KGRound1Message) UnmarshalNTilde() *big.Int { - return new(big.Int).SetBytes(m.GetNTilde()) -} - -func (m *KGRound1Message) UnmarshalH1() *big.Int { - return new(big.Int).SetBytes(m.GetH1()) -} - -func (m *KGRound1Message) UnmarshalH2() *big.Int { - return new(big.Int).SetBytes(m.GetH2()) -} - -func (m *KGRound1Message) UnmarshalDLNProof1() (*dlnproof.Proof, error) { - return dlnproof.UnmarshalDLNProof(m.GetDlnproof_1()) -} - -func (m *KGRound1Message) UnmarshalDLNProof2() (*dlnproof.Proof, error) { - return dlnproof.UnmarshalDLNProof(m.GetDlnproof_2()) + if m.H2 == nil || m.H2.Sign() == 0 { + return false + } + // DLN proofs optional (SNARK mode) + return true } -// ----- // - -func NewKGRound2Message1( - to, from *tss.PartyID, - share *vss.Share, - proof *facproof.ProofFac, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewKGRound1Message constructs a round 1 broadcast message. +func NewKGRound1Message(from *tss.PartyID, ct cmt.HashCommitment, paillierPK *paillier.PublicKey, nTildeI, h1I, h2I *big.Int, dlnProof1, dlnProof2 *dlnproof.Proof) *tss.Message { + return &tss.Message{ From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - } - proofBzs := proof.Bytes() - content := &KGRound2Message1{ - Share: share.Share.Bytes(), - FacProof: proofBzs[:], + IsBroadcast: true, + Content: &KGRound1Message{ + Commitment: ct, + PaillierPK: paillierPK, + NTilde: nTildeI, + H1: h1I, + H2: h2I, + DLNProof1: dlnProof1, + DLNProof2: dlnProof2, + }, } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } +// KGRound2Message1 is a P2P message sent to each other party in +// keygen round 2. Contains the VSS share and optional FacProof. +type KGRound2Message1 struct { + Share *big.Int + FacProof *facproof.ProofFac // nil in on-chain SNARK mode + ReceiverID []byte +} + +// ValidateBasic checks that the share is non-nil and the receiver +// ID is present. func (m *KGRound2Message1) ValidateBasic() bool { return m != nil && - common.NonEmptyBytes(m.GetShare()) - // This is commented for backward compatibility, which msg has no proof - // && common.NonEmptyMultiBytes(m.GetFacProof(), facproof.ProofFacBytesParts) + m.Share != nil && m.Share.Sign() > 0 && + len(m.ReceiverID) > 0 +} + +// NewKGRound2Message1 constructs a round 2 P2P message. +func NewKGRound2Message1(to, from *tss.PartyID, share *vss.Share, proof *facproof.ProofFac) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &KGRound2Message1{ + Share: share.Share, + FacProof: proof, + ReceiverID: to.Key, + }, + } } -func (m *KGRound2Message1) UnmarshalShare() *big.Int { - return new(big.Int).SetBytes(m.Share) +// KGRound2Message2 is broadcast by each party in keygen round 2. +// Contains the decommitment and optional ModProof. +type KGRound2Message2 struct { + DeCommitment cmt.HashDeCommitment + ModProof *modproof.ProofMod // nil in on-chain SNARK mode } -func (m *KGRound2Message1) UnmarshalFacProof() (*facproof.ProofFac, error) { - return facproof.NewProofFromBytes(m.GetFacProof()) +// ValidateBasic checks that the decommitment has at least 2 +// elements (blinding factor + payload). +func (m *KGRound2Message2) ValidateBasic() bool { + return m != nil && len(m.DeCommitment) >= 2 } -// ----- // - -func NewKGRound2Message2( - from *tss.PartyID, - deCommitment cmt.HashDeCommitment, - proof *modproof.ProofMod, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewKGRound2Message2 constructs a round 2 broadcast message. +func NewKGRound2Message2(from *tss.PartyID, deCommitment cmt.HashDeCommitment, proof *modproof.ProofMod) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &KGRound2Message2{ + DeCommitment: deCommitment, + ModProof: proof, + }, } - dcBzs := common.BigIntsToBytes(deCommitment) - proofBzs := proof.Bytes() - content := &KGRound2Message2{ - DeCommitment: dcBzs, - ModProof: proofBzs[:], - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *KGRound2Message2) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.GetDeCommitment()) - // This is commented for backward compatibility, which msg has no proof - // && common.NonEmptyMultiBytes(m.GetModProof(), modproof.ProofModBytesParts) } -func (m *KGRound2Message2) UnmarshalDeCommitment() []*big.Int { - deComBzs := m.GetDeCommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) +// KGRound3Message is broadcast by each party in keygen round 3. +// Contains the Paillier proof (array of big.Int). +type KGRound3Message struct { + PaillierProof paillier.Proof } -func (m *KGRound2Message2) UnmarshalModProof() (*modproof.ProofMod, error) { - return modproof.NewProofFromBytes(m.GetModProof()) -} - -// ----- // - -func NewKGRound3Message( - from *tss.PartyID, - proof paillier.Proof, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - IsBroadcast: true, +// ValidateBasic checks that the proof has the correct number of +// iterations and all elements are non-nil. +func (m *KGRound3Message) ValidateBasic() bool { + if m == nil { + return false } - pfBzs := make([][]byte, len(proof)) - for i := range pfBzs { - if proof[i] == nil { - continue + for _, pi := range m.PaillierProof { + if pi == nil { + return false } - pfBzs[i] = proof[i].Bytes() - } - content := &KGRound3Message{ - PaillierProof: pfBzs, } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) + return true } -func (m *KGRound3Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.GetPaillierProof(), paillier.ProofIters) -} - -func (m *KGRound3Message) UnmarshalProofInts() paillier.Proof { - var pf paillier.Proof - proofBzs := m.GetPaillierProof() - for i := range pf { - pf[i] = new(big.Int).SetBytes(proofBzs[i]) +// NewKGRound3Message constructs a round 3 broadcast message. +func NewKGRound3Message(from *tss.PartyID, proof paillier.Proof) *tss.Message { + return &tss.Message{ + From: from, + IsBroadcast: true, + Content: &KGRound3Message{ + PaillierProof: proof, + }, } - return pf } diff --git a/tss-lib/ecdsa/keygen/messages_test.go b/tss-lib/ecdsa/keygen/messages_test.go new file mode 100644 index 0000000..57b5f80 --- /dev/null +++ b/tss-lib/ecdsa/keygen/messages_test.go @@ -0,0 +1,392 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "bytes" + "math/big" + "testing" + + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestValidateBasicKGRound1(t *testing.T) { + valid := func() *KGRound1Message { + return &KGRound1Message{ + Commitment: big.NewInt(1), + PaillierPK: &paillier.PublicKey{N: big.NewInt(100)}, + NTilde: big.NewInt(2), + H1: big.NewInt(3), + H2: big.NewInt(4), + } + } + + // Happy path. + if !valid().ValidateBasic() { + t.Fatal("valid message should pass") + } + + // Nil receiver. + if (*KGRound1Message)(nil).ValidateBasic() { + t.Fatal("nil receiver should fail") + } + + // Each field nil. + for _, tc := range []struct { + name string + mutate func(m *KGRound1Message) + }{ + {"Commitment nil", func(m *KGRound1Message) { m.Commitment = nil }}, + {"Commitment zero", func(m *KGRound1Message) { m.Commitment = big.NewInt(0) }}, + {"PaillierPK nil", func(m *KGRound1Message) { m.PaillierPK = nil }}, + {"PaillierPK.N nil", func(m *KGRound1Message) { m.PaillierPK = &paillier.PublicKey{N: nil} }}, + {"PaillierPK.N zero", func(m *KGRound1Message) { m.PaillierPK = &paillier.PublicKey{N: big.NewInt(0)} }}, + {"NTilde nil", func(m *KGRound1Message) { m.NTilde = nil }}, + {"NTilde zero", func(m *KGRound1Message) { m.NTilde = big.NewInt(0) }}, + {"H1 nil", func(m *KGRound1Message) { m.H1 = nil }}, + {"H1 zero", func(m *KGRound1Message) { m.H1 = big.NewInt(0) }}, + {"H2 nil", func(m *KGRound1Message) { m.H2 = nil }}, + {"H2 zero", func(m *KGRound1Message) { m.H2 = big.NewInt(0) }}, + } { + t.Run(tc.name, func(t *testing.T) { + m := valid() + tc.mutate(m) + if m.ValidateBasic() { + t.Fatalf("%s: should fail ValidateBasic", tc.name) + } + }) + } +} + +func TestValidateBasicKGRound2Message1(t *testing.T) { + valid := func() *KGRound2Message1 { + return &KGRound2Message1{Share: big.NewInt(1), ReceiverID: []byte("r")} + } + + // Happy path. + if !valid().ValidateBasic() { + t.Fatal("valid should pass") + } + + // Nil receiver. + if (*KGRound2Message1)(nil).ValidateBasic() { + t.Fatal("nil receiver should fail") + } + + for _, tc := range []struct { + name string + mutate func(m *KGRound2Message1) + }{ + {"Share nil", func(m *KGRound2Message1) { m.Share = nil }}, + {"Share zero", func(m *KGRound2Message1) { m.Share = big.NewInt(0) }}, + {"Share negative", func(m *KGRound2Message1) { m.Share = big.NewInt(-1) }}, + {"ReceiverID empty", func(m *KGRound2Message1) { m.ReceiverID = []byte{} }}, + {"ReceiverID nil", func(m *KGRound2Message1) { m.ReceiverID = nil }}, + } { + t.Run(tc.name, func(t *testing.T) { + m := valid() + tc.mutate(m) + if m.ValidateBasic() { + t.Fatalf("%s: should fail ValidateBasic", tc.name) + } + }) + } +} + +func TestValidateBasicKGRound2Message2(t *testing.T) { + // Happy path: exactly 2 elements (minimum valid). + if !(&KGRound2Message2{DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}}).ValidateBasic() { + t.Fatal("valid 2-element decommitment should pass") + } + + // Nil receiver. + if (*KGRound2Message2)(nil).ValidateBasic() { + t.Fatal("nil receiver should fail") + } + + for _, tc := range []struct { + name string + msg *KGRound2Message2 + }{ + {"empty struct", &KGRound2Message2{}}, + {"nil decommitment", &KGRound2Message2{DeCommitment: nil}}, + {"1-element decommitment", &KGRound2Message2{DeCommitment: cmt.HashDeCommitment{big.NewInt(1)}}}, + } { + t.Run(tc.name, func(t *testing.T) { + if tc.msg.ValidateBasic() { + t.Fatalf("%s: should fail ValidateBasic", tc.name) + } + }) + } +} + +func TestValidateBasicKGRound3(t *testing.T) { + makeValid := func() paillier.Proof { + var proof paillier.Proof + for i := range proof { + proof[i] = big.NewInt(int64(i + 1)) + } + return proof + } + + // Happy path. + if !(&KGRound3Message{PaillierProof: makeValid()}).ValidateBasic() { + t.Fatal("valid should pass") + } + + // Nil receiver. + if (*KGRound3Message)(nil).ValidateBasic() { + t.Fatal("nil receiver should fail") + } + + // All-nil proof (zero-value array). + if (&KGRound3Message{}).ValidateBasic() { + t.Fatal("all-nil proof should fail") + } + + // Nil element at each boundary index: first, middle, last. + for _, idx := range []int{0, 5, len(paillier.Proof{}) - 1} { + t.Run("nil_element_"+big.NewInt(int64(idx)).String(), func(t *testing.T) { + proof := makeValid() + proof[idx] = nil + if (&KGRound3Message{PaillierProof: proof}).ValidateBasic() { + t.Fatalf("nil element at index %d should fail", idx) + } + }) + } +} + +// --- Constructor field tests --- + +// TestNewKGRound1MessageFields verifies that NewKGRound1Message populates +// all tss.Message envelope fields and content fields correctly. +func TestNewKGRound1MessageFields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(3) + from := pIDs[0] + + ct := big.NewInt(42) + pk := &paillier.PublicKey{N: big.NewInt(12345)} + nTilde := big.NewInt(100) + h1 := big.NewInt(200) + h2 := big.NewInt(300) + var dlnP1, dlnP2 dlnproof.Proof + for i := range dlnP1.Alpha { + dlnP1.Alpha[i] = big.NewInt(int64(i + 1)) + dlnP1.T[i] = big.NewInt(int64(i + 1)) + dlnP2.Alpha[i] = big.NewInt(int64(i + 100)) + dlnP2.T[i] = big.NewInt(int64(i + 100)) + } + + msg := NewKGRound1Message(from, ct, pk, nTilde, h1, h2, &dlnP1, &dlnP2) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if !msg.IsBroadcast { + t.Fatal("Round1 should be broadcast") + } + if msg.To != nil { + t.Fatal("Broadcast message should have nil To") + } + + // Content checks. + content, ok := msg.Content.(*KGRound1Message) + if !ok { + t.Fatalf("Content type: got %T, want *KGRound1Message", msg.Content) + } + if content.Commitment.Cmp(big.NewInt(42)) != 0 { + t.Fatalf("Commitment: got %v, want 42", content.Commitment) + } + if content.PaillierPK.N.Cmp(big.NewInt(12345)) != 0 { + t.Fatalf("PaillierPK.N: got %v, want 12345", content.PaillierPK.N) + } + if content.NTilde.Cmp(nTilde) != 0 { + t.Fatal("NTilde mismatch") + } + if content.H1.Cmp(h1) != 0 { + t.Fatal("H1 mismatch") + } + if content.H2.Cmp(h2) != 0 { + t.Fatal("H2 mismatch") + } + if content.DLNProof1 == nil || content.DLNProof2 == nil { + t.Fatal("DLN proofs should be non-nil") + } +} + +// TestNewKGRound1MessageNilDLN verifies that DLN proofs can be nil +// (SNARK mode). +func TestNewKGRound1MessageNilDLN(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(2) + msg := NewKGRound1Message(pIDs[0], big.NewInt(1), + &paillier.PublicKey{N: big.NewInt(100)}, + big.NewInt(2), big.NewInt(3), big.NewInt(4), + nil, nil) + + content := msg.Content.(*KGRound1Message) + if content.DLNProof1 != nil || content.DLNProof2 != nil { + t.Fatal("DLN proofs should be nil in SNARK mode") + } + if !content.ValidateBasic() { + t.Fatal("message with nil DLN proofs should still pass ValidateBasic") + } +} + +// TestNewKGRound2Message1Fields verifies that NewKGRound2Message1 +// produces a P2P message with correct From, To, ReceiverID, and share. +func TestNewKGRound2Message1Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(3) + from := pIDs[0] + to := pIDs[1] + + share := &vss.Share{ + Threshold: 1, + ID: big.NewInt(7), + Share: big.NewInt(999), + } + + msg := NewKGRound2Message1(to, from, share, nil) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if msg.IsBroadcast { + t.Fatal("Round2Message1 should NOT be broadcast") + } + if len(msg.To) != 1 || msg.To[0] != to { + t.Fatalf("To: got %v, want [%v]", msg.To, to) + } + + // Content checks. + content, ok := msg.Content.(*KGRound2Message1) + if !ok { + t.Fatalf("Content type: got %T, want *KGRound2Message1", msg.Content) + } + if content.Share.Cmp(big.NewInt(999)) != 0 { + t.Fatalf("Share: got %v, want 999", content.Share) + } + if !bytes.Equal(content.ReceiverID, to.Key) { + t.Fatalf("ReceiverID: got %x, want %x", content.ReceiverID, to.Key) + } + if content.FacProof != nil { + t.Fatal("FacProof should be nil when passed nil") + } +} + +// TestNewKGRound2Message2Fields verifies that NewKGRound2Message2 +// produces a broadcast message with the correct decommitment. +func TestNewKGRound2Message2Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(3) + from := pIDs[2] + + deC := cmt.HashDeCommitment{big.NewInt(10), big.NewInt(20), big.NewInt(30)} + + msg := NewKGRound2Message2(from, deC, nil) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if !msg.IsBroadcast { + t.Fatal("Round2Message2 should be broadcast") + } + if msg.To != nil { + t.Fatal("Broadcast message should have nil To") + } + + // Content checks. + content, ok := msg.Content.(*KGRound2Message2) + if !ok { + t.Fatalf("Content type: got %T, want *KGRound2Message2", msg.Content) + } + if len(content.DeCommitment) != 3 { + t.Fatalf("DeCommitment length: got %d, want 3", len(content.DeCommitment)) + } + for i, v := range []int64{10, 20, 30} { + if content.DeCommitment[i].Cmp(big.NewInt(v)) != 0 { + t.Fatalf("DeCommitment[%d]: got %v, want %d", i, content.DeCommitment[i], v) + } + } + if content.ModProof != nil { + t.Fatal("ModProof should be nil when passed nil") + } +} + +// TestNewKGRound3MessageFields verifies that NewKGRound3Message +// produces a broadcast message with the correct Paillier proof. +func TestNewKGRound3MessageFields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(3) + from := pIDs[1] + + var proof paillier.Proof + for i := range proof { + proof[i] = big.NewInt(int64(i * 7)) + } + + msg := NewKGRound3Message(from, proof) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if !msg.IsBroadcast { + t.Fatal("Round3 should be broadcast") + } + if msg.To != nil { + t.Fatal("Broadcast message should have nil To") + } + + // Content checks. + content, ok := msg.Content.(*KGRound3Message) + if !ok { + t.Fatalf("Content type: got %T, want *KGRound3Message", msg.Content) + } + for i := range content.PaillierProof { + expected := big.NewInt(int64(i * 7)) + if content.PaillierProof[i].Cmp(expected) != 0 { + t.Fatalf("PaillierProof[%d]: got %v, want %v", i, content.PaillierProof[i], expected) + } + } +} + +func TestExportR2BcastSelf(t *testing.T) { + // ExportR2BcastSelf returns the stored message for own index. + st := &KeygenState{ + params: nil, // not needed for export + } + // Just verify it doesn't panic on zero state. + // In real usage this is called after Round2. + defer func() { + _ = recover() // expected — params is nil + }() + _ = st.ExportR2BcastSelf() +} + +func TestValidateSaveData(t *testing.T) { + empty := NewLocalPartySaveData(0) + if err := empty.ValidateSaveData(); err == nil { + t.Fatal("empty save data should fail validation") + } +} + +func TestBuildLocalSaveDataSubset(t *testing.T) { + // BuildLocalSaveDataSubset panics on missing key — verify it does. + defer func() { + if r := recover(); r == nil { + t.Fatal("expected panic for missing signer key") + } + }() + sd := NewLocalPartySaveData(2) + sd.Ks = []*big.Int{big.NewInt(1), big.NewInt(2)} + // Pass an ID whose key doesn't match anything in Ks. + fakeIDs := tss.GenerateTestPartyIDs(1) + BuildLocalSaveDataSubset(sd, fakeIDs) +} diff --git a/tss-lib/ecdsa/keygen/preparams_test.go b/tss-lib/ecdsa/keygen/preparams_test.go new file mode 100644 index 0000000..d42e72b --- /dev/null +++ b/tss-lib/ecdsa/keygen/preparams_test.go @@ -0,0 +1,29 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "encoding/json" + "testing" + + _ "embed" +) + +//go:embed testdata/preparams.json +var embeddedPreParams []byte + +// loadTestPreParams returns n pre-computed LocalPreParams from the +// embedded fixture. Internal to keygen tests to avoid import cycles. +func loadTestPreParams(t *testing.T, n int) []LocalPreParams { + t.Helper() + var params []LocalPreParams + if err := json.Unmarshal(embeddedPreParams, ¶ms); err != nil { + t.Fatalf("parse embedded preparams: %v", err) + } + if n > len(params) { + t.Fatalf("need %d preparams, fixture has %d", n, len(params)) + } + return params[:n] +} diff --git a/tss-lib/ecdsa/keygen/prepare.go b/tss-lib/ecdsa/keygen/prepare.go index 5670fd7..6e48615 100644 --- a/tss-lib/ecdsa/keygen/prepare.go +++ b/tss-lib/ecdsa/keygen/prepare.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen @@ -10,13 +9,14 @@ import ( "context" "crypto/rand" "errors" + "fmt" "io" "math/big" "runtime" "time" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" ) const ( @@ -139,6 +139,13 @@ consumer: f1 := common.GetRandomPositiveRelativelyPrimeInt(rand, NTildei) alpha := common.GetRandomPositiveRelativelyPrimeInt(rand, NTildei) beta := modPQ.ModInverse(alpha) + // [FORK] Nil check on ModInverse result: upstream did not check. ModInverse returns nil + // when alpha is not coprime with p*q, which would cause a nil-pointer panic downstream + // when computing DLN proofs. This is astronomically unlikely with random alpha but + // defense-in-depth against degenerate RNG output. + if beta == nil { + return nil, fmt.Errorf("alpha modular inverse failed: alpha not coprime with p*q") + } h1i := modNTildeI.Mul(f1, f1) h2i := modNTildeI.Exp(h1i, alpha) diff --git a/tss-lib/ecdsa/keygen/prepare_edge_test.go b/tss-lib/ecdsa/keygen/prepare_edge_test.go new file mode 100644 index 0000000..91ac0c3 --- /dev/null +++ b/tss-lib/ecdsa/keygen/prepare_edge_test.go @@ -0,0 +1,292 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "context" + "crypto/rand" + "errors" + "io" + "reflect" + "sync/atomic" + "testing" + "time" +) + +// TestGeneratePreParamsMultipleConcurrencyArgsPanics verifies that passing more +// than one optionalConcurrency argument triggers a panic, as documented by the +// function contract. +func TestGeneratePreParamsMultipleConcurrencyArgsPanics(t *testing.T) { + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("expected panic when multiple concurrency args are provided") + } + }() + ctx := context.Background() + _, _ = GeneratePreParamsWithContextAndRandom(ctx, rand.Reader, 2, 4) + }() +} + +// TestGeneratePreParamsContextAlreadyCancelled verifies that passing an +// already-cancelled context returns an error immediately without blocking. +func TestGeneratePreParamsContextAlreadyCancelled(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // cancel immediately before calling + + start := time.Now() + preParams, err := GeneratePreParamsWithContext(ctx, 1) + elapsed := time.Since(start) + + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("should return an error with cancelled context") + } + if elapsed >= 2*time.Second { + t.Fatal("should return quickly, not block on prime generation") + } +} + +// TestGeneratePreParamsContextAlreadyCancelledAndRandom exercises the +// WithContextAndRandom variant with an already-cancelled context. +func TestGeneratePreParamsContextAlreadyCancelledAndRandom(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + start := time.Now() + preParams, err := GeneratePreParamsWithContextAndRandom(ctx, rand.Reader, 1) + elapsed := time.Since(start) + + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("expected error") + } + if elapsed >= 2*time.Second { + t.Fatalf("expected %v < %v", elapsed, 2*time.Second) + } +} + +// TestGeneratePreParamsZeroConcurrency verifies that passing concurrency=0 +// does not panic and is handled gracefully (the code divides by 3 and clamps +// to minimum 1). +func TestGeneratePreParamsZeroConcurrency(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) + defer cancel() + + // Should not panic even with concurrency=0; the function clamps to 1. + preParams, err := GeneratePreParamsWithContextAndRandom(ctx, rand.Reader, 0) + // Will timeout (5ms is too short for real primes), but should not panic. + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("expected error") + } +} + +// TestGeneratePreParamsNegativeConcurrency verifies that a negative +// concurrency value is handled gracefully (clamped to 1 after division). +func TestGeneratePreParamsNegativeConcurrency(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) + defer cancel() + + preParams, err := GeneratePreParamsWithContextAndRandom(ctx, rand.Reader, -3) + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("expected error") + } +} + +// failingReader is an io.Reader that always returns an error. +// It exercises the error path when the rand reader fails during prime generation. +type failingReader struct{} + +func (f *failingReader) Read([]byte) (int, error) { + return 0, errors.New("simulated RNG failure") +} + +// TestGeneratePreParamsFailingRandReader verifies that a broken rand reader +// causes an error (not a panic) and returns promptly. +func TestGeneratePreParamsFailingRandReader(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + preParams, err := GeneratePreParamsWithContextAndRandom(ctx, &failingReader{}, 1) + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("should return an error when rand reader fails") + } +} + +// countingReader wraps an io.Reader and counts how many bytes are read. +// Used to verify that a custom rand reader is actually being consumed. +// bytesRead uses atomic access because the production code passes the +// reader to multiple concurrent goroutines. +type countingReader struct { + inner io.Reader + bytesRead atomic.Int64 +} + +func (c *countingReader) Read(p []byte) (int, error) { + n, err := c.inner.Read(p) + c.bytesRead.Add(int64(n)) + return n, err +} + +// TestGeneratePreParamsCustomRandIsUsed verifies that the custom rand.Reader +// parameter is actually consumed during prime generation. We use a short +// timeout so we don't wait for full prime generation, but even the initial +// attempts should read from our custom reader. +func TestGeneratePreParamsCustomRandIsUsed(t *testing.T) { + cr := &countingReader{inner: rand.Reader} + + ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) + defer cancel() + + // Will almost certainly timeout, but that's fine — we just want to confirm + // the custom reader was used. + _, _ = GeneratePreParamsWithContextAndRandom(ctx, cr, 1) + + if cr.bytesRead.Load() <= int64(0) { + t.Fatal("custom rand reader should have been read from") + } +} + +// TestGeneratePreParamsResultValidates generates real pre-params (slow!) and +// verifies that both Validate() and ValidateWithProof() return true, and that +// all fields are non-nil with correct algebraic relationships. +func TestGeneratePreParamsResultValidates(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow safe prime generation in short mode") + } + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) + defer cancel() + + preParams, err := GeneratePreParamsWithContextAndRandom(ctx, rand.Reader, 1) + if err != nil { + t.Fatalf("GeneratePreParams should succeed with sufficient timeout"+": %v", err) + } + if preParams == nil { + t.Fatal("expected non-nil") + } + + // Structural validation (nil checks) + if !preParams.Validate() { + t.Fatal("Validate() should return true") + } + + // Full algebraic validation (NTilde = (2P+1)(2Q+1), H2 = H1^Alpha mod NTilde) + if !preParams.ValidateWithProof() { + t.Fatal("ValidateWithProof() should return true") + } + + // Verify all fields are populated + if preParams.PaillierSK == nil { + t.Fatal("expected non-nil") + } + if preParams.PaillierSK.N == nil { + t.Fatal("expected non-nil") + } + if preParams.PaillierSK.LambdaN == nil { + t.Fatal("expected non-nil") + } + if preParams.NTildei == nil { + t.Fatal("expected non-nil") + } + if preParams.H1i == nil { + t.Fatal("expected non-nil") + } + if preParams.H2i == nil { + t.Fatal("expected non-nil") + } + if preParams.Alpha == nil { + t.Fatal("expected non-nil") + } + if preParams.Beta == nil { + t.Fatal("expected non-nil") + } + if preParams.P == nil { + t.Fatal("expected non-nil") + } + if preParams.Q == nil { + t.Fatal("expected non-nil") + } + + // P != Q (defense-in-depth — astronomically unlikely but tested) + if preParams.P.Cmp(preParams.Q) == 0 { + t.Fatalf("P and Q should be distinct") + } + + // Bit lengths: P, Q should be ~1024-bit safe primes (their "prime" halves) + if preParams.P.BitLen() < 1000 { + t.Fatal("P bit length should be ~1024") + } + if preParams.Q.BitLen() < 1000 { + t.Fatal("Q bit length should be ~1024") + } + + // NTilde bit length should be ~2048 + if preParams.NTildei.BitLen() < 2000 { + t.Fatal("NTilde should be ~2048 bits") + } + + // Paillier modulus should be 2048 bits + if !reflect.DeepEqual(paillierModulusLen, preParams.PaillierSK.N.BitLen()) { + t.Fatalf("Paillier modulus should be exactly 2048 bits") + } +} + +// TestGeneratePreParamsTimeoutWrapper verifies that the timeout-based wrapper +// GeneratePreParams correctly propagates context cancellation. +func TestGeneratePreParamsTimeoutWrapper(t *testing.T) { + // 1ms timeout — will definitely fail, but should return an error not panic + start := time.Now() + preParams, err := GeneratePreParams(1*time.Millisecond, 1) + elapsed := time.Since(start) + + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("expected error") + } + if elapsed >= 5*time.Second { + t.Fatal("should respect the timeout") + } +} + +// TestGeneratePreParamsWithContextCallsWithContextAndRandom verifies that +// GeneratePreParamsWithContext delegates to GeneratePreParamsWithContextAndRandom. +// We do this by passing a cancelled context — both functions should behave +// identically. +func TestGeneratePreParamsWithContextCallsWithContextAndRandom(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + pp1, err1 := GeneratePreParamsWithContext(ctx, 1) + pp2, err2 := GeneratePreParamsWithContextAndRandom(ctx, rand.Reader, 1) + + if pp1 != nil { + t.Fatalf("expected nil, got %v", pp1) + } + if pp2 != nil { + t.Fatalf("expected nil, got %v", pp2) + } + if err1 == nil { + t.Fatal("expected error") + } + if err2 == nil { + t.Fatal("expected error") + } +} diff --git a/tss-lib/ecdsa/keygen/prepare_test.go b/tss-lib/ecdsa/keygen/prepare_test.go index f00e8e8..a6fd417 100644 --- a/tss-lib/ecdsa/keygen/prepare_test.go +++ b/tss-lib/ecdsa/keygen/prepare_test.go @@ -10,17 +10,21 @@ import ( "context" "testing" "time" - - "github.com/stretchr/testify/assert" ) func TestGeneratePreParamsTimeout(t *testing.T) { start := time.Now() preParams, err := GeneratePreParams(5*time.Millisecond, 1) - assert.Nil(t, preParams) - assert.NotNil(t, err) - assert.WithinDuration(t, start, time.Now(), 1*time.Second) + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("expected non-nil") + } + if diff := time.Since(start); diff < 0 || diff > 1*time.Second { + t.Fatalf("duration %v exceeds %v", diff, 1*time.Second) + } } func TestGeneratePreParamsWithContextTimeout(t *testing.T) { @@ -30,9 +34,15 @@ func TestGeneratePreParamsWithContextTimeout(t *testing.T) { start := time.Now() preParams, err := GeneratePreParamsWithContext(ctx, 1) - assert.Nil(t, preParams) - assert.NotNil(t, err) - assert.WithinDuration(t, start, time.Now(), 1*time.Second) + if preParams != nil { + t.Fatalf("expected nil, got %v", preParams) + } + if err == nil { + t.Fatal("expected non-nil") + } + if diff := time.Since(start); diff < 0 || diff > 1*time.Second { + t.Fatalf("duration %v exceeds %v", diff, 1*time.Second) + } } func TestGenerateWithContext(t *testing.T) { @@ -40,14 +50,34 @@ func TestGenerateWithContext(t *testing.T) { defer cancel() preParams, err := GeneratePreParamsWithContext(ctx, 1) - assert.NotNil(t, preParams) - assert.Nil(t, err) - assert.NotNil(t, preParams.PaillierSK) - assert.NotNil(t, preParams.NTildei) - assert.NotNil(t, preParams.H1i) - assert.NotNil(t, preParams.H2i) - assert.NotNil(t, preParams.Alpha) - assert.NotNil(t, preParams.Beta) - assert.NotNil(t, preParams.P) - assert.NotNil(t, preParams.Q) + if preParams == nil { + t.Fatal("expected non-nil") + } + if err != nil { + t.Fatalf("expected nil, got %v", err) + } + if preParams.PaillierSK == nil { + t.Fatal("expected non-nil") + } + if preParams.NTildei == nil { + t.Fatal("expected non-nil") + } + if preParams.H1i == nil { + t.Fatal("expected non-nil") + } + if preParams.H2i == nil { + t.Fatal("expected non-nil") + } + if preParams.Alpha == nil { + t.Fatal("expected non-nil") + } + if preParams.Beta == nil { + t.Fatal("expected non-nil") + } + if preParams.P == nil { + t.Fatal("expected non-nil") + } + if preParams.Q == nil { + t.Fatal("expected non-nil") + } } diff --git a/tss-lib/ecdsa/keygen/round1_negative_test.go b/tss-lib/ecdsa/keygen/round1_negative_test.go new file mode 100644 index 0000000..09f223e --- /dev/null +++ b/tss-lib/ecdsa/keygen/round1_negative_test.go @@ -0,0 +1,315 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "bytes" + "context" + "strings" + "testing" + "time" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +const ( + testN = 3 + testThreshold = 1 // 2-of-3 +) + +// makeTestParams creates a standard 3-party, threshold=1 parameter set for +// party 0 with all expensive proofs disabled. Returns params, sorted +// party IDs, and the peer context so callers can create params for +// other parties or re-create params with the same party set. +func makeTestParams() (*tss.Parameters, tss.SortedPartyIDs, *tss.PeerContext) { + pIDs := tss.GenerateTestPartyIDs(testN) + peerCtx := tss.NewPeerContext(pIDs) + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], testN, testThreshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + return params, pIDs, peerCtx +} + +// TestRound1WithInvalidPreParamsGeneratesFresh passes zero-value +// pre-params (which fail both Validate and ValidateWithProof) and +// verifies that Round1 still succeeds by generating fresh safe primes. +// +// NOTE: This test is slow (~30-120s) because it generates safe primes +// on the fly. Run with -timeout 5m. +func TestRound1WithInvalidPreParamsGeneratesFresh(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow test in short mode") + } + + params, _, _ := makeTestParams() + + // Zero-value LocalPreParams: all fields nil, so Validate() returns false + // and ValidateWithProof() returns false. Round1 should fall through to + // the fresh-generation branch. + var emptyPreParams LocalPreParams + + // Sanity: confirm our zero-value pre-params are indeed invalid. + if emptyPreParams.Validate() { + t.Fatal("expected zero-value preParams to fail Validate()") + } + if emptyPreParams.ValidateWithProof() { + t.Fatal("expected zero-value preParams to fail ValidateWithProof()") + } + + state, out, err := Round1(context.Background(), params, emptyPreParams) + if err != nil { + t.Fatalf("Round1 with empty preParams should generate fresh ones, got error: %v", err) + } + if state == nil { + t.Fatal("expected non-nil state") + } + if out == nil || len(out.Messages) == 0 { + t.Fatal("expected non-nil output with messages") + } + + // Verify the generated pre-params are valid. + if !state.save.Validate() { + t.Fatal("freshly generated preParams should pass Validate()") + } + if !state.save.ValidateWithProof() { + t.Fatal("freshly generated preParams should pass ValidateWithProof()") + } + + // Verify the round 1 message is well-formed. + r1msg := out.Messages[0].Content.(*KGRound1Message) + if !r1msg.ValidateBasic() { + t.Fatal("round 1 message should pass ValidateBasic()") + } +} + +// TestRound1RejectsStalePreParams tests that pre-params which pass the +// basic Validate() but fail ValidateWithProof() (simulating old-format +// pre-params) cause Round1 to return an error rather than silently +// proceeding with bad parameters. +func TestRound1RejectsStalePreParams(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow test in short mode") + } + + params, _, _ := makeTestParams() + + // Generate valid pre-params, then corrupt them so that Validate() + // passes but ValidateWithProof() fails. The easiest way: zero out + // the Alpha field (needed by ValidateWithProof's H2 = H1^Alpha check). + pps := loadTestPreParams(t, 1) + pp := &pps[0] + + // Confirm it's initially valid. + if !pp.Validate() || !pp.ValidateWithProof() { + t.Fatal("generated preParams should be valid") + } + + // Corrupt: nil out Alpha so ValidateWithProof fails but Validate passes. + stale := *pp + stale.Alpha = nil + + if !stale.Validate() { + t.Fatal("stale preParams should still pass basic Validate()") + } + if stale.ValidateWithProof() { + t.Fatal("stale preParams should fail ValidateWithProof()") + } + + _, _, err := Round1(context.Background(), params, stale) + if err == nil { + t.Fatal("expected error for stale preParams, got nil") + } + if !strings.Contains(err.Error(), "preParams failed validation") { + t.Fatalf("expected 'preParams failed validation' error, got: %v", err) + } +} + +// TestRound1RejectsContextCancellation passes a pre-cancelled context +// and verifies that Round1 returns an error when it needs to generate +// fresh pre-params (the only code path that checks ctx). +func TestRound1RejectsContextCancellation(t *testing.T) { + params, _, _ := makeTestParams() + + // Use a very short timeout to trigger the generation timeout path. + params.SetSafePrimeGenTimeout(1 * time.Millisecond) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() // pre-cancel + + // Zero-value pre-params forces the generation branch. + var emptyPreParams LocalPreParams + + _, _, err := Round1(ctx, params, emptyPreParams) + if err == nil { + t.Fatal("expected error from cancelled context, got nil") + } + // The error message comes from Round1 wrapping the generation failure. + if !strings.Contains(err.Error(), "pre-params generation failed") { + t.Fatalf("expected 'pre-params generation failed' error, got: %v", err) + } +} + +// TestRound1ExportsCorrectSSIDNonce sets a specific SSID nonce on +// the parameters and verifies that two different nonces produce +// different SSIDs. Uses the same party IDs and pre-params for +// both runs so the only variable is the nonce. +func TestRound1ExportsCorrectSSIDNonce(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow test in short mode") + } + + // Generate shared pre-params and party IDs (reuse across both runs). + pps := loadTestPreParams(t, 1) + pp := &pps[0] + + pIDs := tss.GenerateTestPartyIDs(testN) + peerCtx := tss.NewPeerContext(pIDs) + + runRound1WithNonce := func(nonce uint) *KeygenState { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], testN, testThreshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + params.SetSSIDNonce(nonce) + + state, _, err := Round1(context.Background(), params, *pp) + if err != nil { + t.Fatalf("Round1 with nonce=%d: %v", nonce, err) + } + return state + } + + state0 := runRound1WithNonce(0) + state1 := runRound1WithNonce(1) + + // Access internal SSID via temp.ssid (package-level test access). + ssid0 := state0.temp.ssid + ssid1 := state1.temp.ssid + + if ssid0 == nil || ssid1 == nil { + t.Fatal("SSID should be non-nil after Round1") + } + if bytes.Equal(ssid0, ssid1) { + t.Fatalf("different SSIDNonce values (0 vs 1) should produce different SSIDs, got same: %x", ssid0) + } + + // Verify the ssidNonce temp field was set correctly. + if state0.temp.ssidNonce.Uint64() != 0 { + t.Fatalf("expected ssidNonce=0, got %d", state0.temp.ssidNonce.Uint64()) + } + if state1.temp.ssidNonce.Uint64() != 1 { + t.Fatalf("expected ssidNonce=1, got %d", state1.temp.ssidNonce.Uint64()) + } +} + +// TestRound1WithCeremonyID sets a CeremonyID on params, runs Round1, +// and verifies that the SSID includes the ceremony ID by comparing +// SSIDs with and without a CeremonyID set. Uses the same party IDs +// and pre-params for all runs so the only variable is the CeremonyID. +func TestRound1WithCeremonyID(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow test in short mode") + } + + // Generate shared pre-params and party IDs. + pps := loadTestPreParams(t, 1) + pp := &pps[0] + + pIDs := tss.GenerateTestPartyIDs(testN) + peerCtx := tss.NewPeerContext(pIDs) + + runRound1WithCeremonyID := func(ceremonyID []byte) *KeygenState { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], testN, testThreshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + if ceremonyID != nil { + params.SetCeremonyID(ceremonyID) + } + + state, _, err := Round1(context.Background(), params, *pp) + if err != nil { + t.Fatalf("Round1 with ceremonyID=%x: %v", ceremonyID, err) + } + return state + } + + // Run without CeremonyID. + stateNoCID := runRound1WithCeremonyID(nil) + + // Run with CeremonyID = "test-ceremony-42". + stateWithCID := runRound1WithCeremonyID([]byte("test-ceremony-42")) + + // Run with a different CeremonyID. + stateWithCID2 := runRound1WithCeremonyID([]byte("test-ceremony-99")) + + ssidNone := stateNoCID.temp.ssid + ssidCID := stateWithCID.temp.ssid + ssidCID2 := stateWithCID2.temp.ssid + + if ssidNone == nil || ssidCID == nil || ssidCID2 == nil { + t.Fatal("SSIDs should be non-nil after Round1") + } + + // CeremonyID is included in the SSID hash. Different CeremonyIDs + // (including nil vs non-nil) must produce different SSIDs. + if bytes.Equal(ssidNone, ssidCID) { + t.Fatal("SSID with no CeremonyID should differ from SSID with CeremonyID") + } + if bytes.Equal(ssidCID, ssidCID2) { + t.Fatal("SSIDs with different CeremonyIDs should differ") + } + if bytes.Equal(ssidNone, ssidCID2) { + t.Fatal("SSID with no CeremonyID should differ from SSID with CeremonyID 2") + } +} + +// TestRound1CeremonyIDCausesCrossPartyMismatch verifies that if two +// parties use different CeremonyIDs, their SSIDs diverge. This is +// the functional proof that CeremonyID is correctly bound into the +// protocol transcript. +func TestRound1CeremonyIDCausesCrossPartyMismatch(t *testing.T) { + if testing.Short() { + t.Skip("skipping slow test in short mode") + } + + preParams := loadTestPreParams(t, testN) + + pIDs := tss.GenerateTestPartyIDs(testN) + peerCtx := tss.NewPeerContext(pIDs) + + // Party 0 and 1 use CeremonyID "A", party 2 uses CeremonyID "B". + states := make([]*KeygenState, testN) + for i := 0; i < testN; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], testN, testThreshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + if i < 2 { + params.SetCeremonyID([]byte("ceremony-A")) + } else { + params.SetCeremonyID([]byte("ceremony-B")) + } + + st, _, err := Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + } + + // Parties with different CeremonyIDs should have different SSIDs. + if bytes.Equal(states[0].temp.ssid, states[2].temp.ssid) { + t.Fatal("parties with different CeremonyIDs should have different SSIDs") + } + + // Parties with the same CeremonyID should have the same SSID, + // because getSSID does not include the individual party index -- + // only the full sorted party key list, which is shared. + if !bytes.Equal(states[0].temp.ssid, states[1].temp.ssid) { + t.Fatal("parties with the same CeremonyID should have the same SSID") + } +} diff --git a/tss-lib/ecdsa/keygen/round2_negative_test.go b/tss-lib/ecdsa/keygen/round2_negative_test.go new file mode 100644 index 0000000..948c430 --- /dev/null +++ b/tss-lib/ecdsa/keygen/round2_negative_test.go @@ -0,0 +1,443 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// round1Fixture holds the state and messages produced by a valid 3-party +// keygen Round1. Negative tests corrupt one message and call Round2 on +// party 0 to assert the expected rejection. +type round1Fixture struct { + states []*KeygenState + allR1 []*tss.Message // allR1[j] = party j's broadcast + n int + pIDs tss.SortedPartyIDs + peerCtx *tss.PeerContext +} + +// setupRound1ForNegativeTests runs a real 3-party keygen Round1 with +// all DLN proofs disabled (NoProofDLN mode) so that corrupted parameters +// trigger the parameter-validation checks rather than DLN proof failures. +// Returns a fixture whose allR1 slice the caller can mutate before +// calling Round2 on states[0]. +func setupRound1ForNegativeTests(t *testing.T) *round1Fixture { + t.Helper() + const n = 3 + const threshold = 1 // 2-of-3 + + preParams := loadTestPreParams(t, n) + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states := make([]*KeygenState, n) + allR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + allR1[i] = out.Messages[0] + } + + return &round1Fixture{ + states: states, + allR1: allR1, + n: n, + pIDs: pIDs, + peerCtx: peerCtx, + } +} + +// cloneR1Msgs returns a shallow copy of the allR1 slice so that the +// caller can replace individual entries without affecting the original. +func cloneR1Msgs(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + copy(out, msgs) + return out +} + +// cloneR1MsgContent deep-copies the KGRound1Message content of +// allR1[idx] so that field mutations do not corrupt the original. +func cloneR1MsgContent(msg *tss.Message) *tss.Message { + orig := msg.Content.(*KGRound1Message) + clone := &KGRound1Message{ + Commitment: new(big.Int).Set(orig.Commitment), + PaillierPK: &paillier.PublicKey{N: new(big.Int).Set(orig.PaillierPK.N)}, + NTilde: new(big.Int).Set(orig.NTilde), + H1: new(big.Int).Set(orig.H1), + H2: new(big.Int).Set(orig.H2), + DLNProof1: orig.DLNProof1, + DLNProof2: orig.DLNProof2, + } + return &tss.Message{ + From: msg.From, + To: msg.To, + IsBroadcast: msg.IsBroadcast, + Content: clone, + } +} + +// expectRound2Error calls Round2 on party 0 with the given messages and +// asserts that the returned error contains the expected substring and +// identifies the correct culprit party. +func expectRound2Error(t *testing.T, fix *round1Fixture, msgs []*tss.Message, wantErrSubstr string, wantCulpritIdx int) { + t.Helper() + _, err := Round2(context.Background(), fix.states[0], msgs) + if err == nil { + t.Fatalf("expected error containing %q, got nil", wantErrSubstr) + } + if !strings.Contains(err.Error(), wantErrSubstr) { + t.Fatalf("expected error containing %q, got: %v", wantErrSubstr, err) + } + var tssErr *tss.Error + if ok := isError(err, &tssErr); !ok { + t.Fatal("expected a *tss.Error with culprit information") + } + culprits := tssErr.Culprits() + if len(culprits) != 1 || culprits[0].Index != wantCulpritIdx { + t.Fatalf("expected culprit index %d, got: %v", wantCulpritIdx, culprits) + } +} + +// victimIndex returns the index of a party whose message we corrupt. +// We pick party 1 (not party 0, which is the verifier). +const victimIdx = 1 + +// --- Individual parameter validation tests --- + +func TestRound2RejectsPaillierNInsufficientBits(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + bad.Content.(*KGRound1Message).PaillierPK.N = big.NewInt(1023) // tiny, far below 2048 bits + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "paillier modulus insufficient bits", victimIdx) +} + +func TestRound2RejectsEvenPaillierN(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + // Make N even but keep 2048 bits: set bit 0 to 0. + n := bad.Content.(*KGRound1Message).PaillierPK.N + n.SetBit(n, 0, 0) + // Ensure still 2048 bits by setting bit 2047. + n.SetBit(n, 2047, 1) + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "even paillier modulus", victimIdx) +} + +func TestRound2RejectsPrimePaillierN(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + // Use a known 2048-bit prime. We construct one by taking a random + // 2048-bit odd number and finding the next prime. For test + // determinism, use a fixed seed. + prime, _ := new(big.Int).SetString( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"+ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"+ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"+ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"+ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"+ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + // This is the 2048-bit MODP prime from RFC 3526. It is indeed prime. + if prime.BitLen() != 2048 || !prime.ProbablyPrime(20) { + t.Fatal("test setup: expected a 2048-bit prime") + } + bad.Content.(*KGRound1Message).PaillierPK.N = prime + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "prime paillier modulus", victimIdx) +} + +func TestRound2RejectsPerfectSquarePaillierN(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + // Use a 1024-bit prime p, then set N = p*p which should be 2048 bits. + // Try P first, then Q — one of them will produce a 2048-bit square. + p := fix.states[0].save.PaillierSK.P + pp := new(big.Int).Mul(p, p) + if pp.BitLen() != 2048 { + q := fix.states[0].save.PaillierSK.Q + pp = new(big.Int).Mul(q, q) + } + if pp.BitLen() != 2048 { + t.Skip("neither p*p nor q*q is 2048 bits; skipping") + } + bad.Content.(*KGRound1Message).PaillierPK.N = pp + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "perfect-square paillier modulus", victimIdx) +} + +func TestRound2RejectsH1EqualsH2(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + content := bad.Content.(*KGRound1Message) + content.H2 = new(big.Int).Set(content.H1) // H1 == H2 + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "h1j == h2j", victimIdx) +} + +func TestRound2RejectsH1IsOne(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + bad.Content.(*KGRound1Message).H1 = big.NewInt(1) + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "h1j or h2j is 1", victimIdx) +} + +func TestRound2RejectsH2IsOne(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + bad.Content.(*KGRound1Message).H2 = big.NewInt(1) + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "h1j or h2j is 1", victimIdx) +} + +func TestRound2RejectsNTildeInsufficientBits(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + bad.Content.(*KGRound1Message).NTilde = big.NewInt(999) // tiny + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "NTildej insufficient bits", victimIdx) +} + +func TestRound2RejectsEvenNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + nt := bad.Content.(*KGRound1Message).NTilde + nt.SetBit(nt, 0, 0) // make even + nt.SetBit(nt, 2047, 1) // keep 2048 bits + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "even NTildej", victimIdx) +} + +func TestRound2RejectsPrimeNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + // Reuse the RFC 3526 2048-bit prime. + prime, _ := new(big.Int).SetString( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"+ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"+ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"+ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"+ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"+ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + bad.Content.(*KGRound1Message).NTilde = prime + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "prime NTildej", victimIdx) +} + +func TestRound2RejectsPerfectSquareNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + p := fix.states[0].save.PaillierSK.P + pp := new(big.Int).Mul(p, p) + if pp.BitLen() != 2048 { + q := fix.states[0].save.PaillierSK.Q + pp = new(big.Int).Mul(q, q) + } + if pp.BitLen() != 2048 { + t.Skip("neither p*p nor q*q is 2048 bits; skipping") + } + bad.Content.(*KGRound1Message).NTilde = pp + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "perfect-square NTildej", victimIdx) +} + +func TestRound2RejectsPaillierNEqualsNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + content := bad.Content.(*KGRound1Message) + // Set NTilde = PaillierPK.N (both already 2048-bit semiprimes). + content.NTilde = new(big.Int).Set(content.PaillierPK.N) + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "paillier N == NTilde", victimIdx) +} + +func TestRound2RejectsH1NotCoprimeNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + content := bad.Content.(*KGRound1Message) + // NTilde = safePrime_P * safePrime_Q. We grab one of the safe prime + // factors from the victim's pre-params (party 1) and set H1 to it, + // so gcd(H1, NTilde) != 1. + // + // party 1's NTilde = (2*P+1)*(2*Q+1). We need a factor. The + // simplest approach: set H1 = safeP = 2*P+1. + pPrep := fix.states[victimIdx].save.P + safeP := new(big.Int).Mul(pPrep, big.NewInt(2)) + safeP.Add(safeP, big.NewInt(1)) + content.H1 = safeP + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "h1j not coprime with NTildej", victimIdx) +} + +func TestRound2RejectsH2NotCoprimeNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + content := bad.Content.(*KGRound1Message) + // Same approach as H1 test but corrupt H2. + pPrep := fix.states[victimIdx].save.P + safeP := new(big.Int).Mul(pPrep, big.NewInt(2)) + safeP.Add(safeP, big.NewInt(1)) + // Keep H1 valid, set H2 = safeP (a factor of NTilde). + content.H2 = safeP + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "h2j not coprime with NTildej", victimIdx) +} + +func TestRound2RejectsDuplicateH2(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Clone party 2's message and set its H2 to party 0's H2. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).H2 = new(big.Int).Set(party0Content.H2) + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate h2j", 2) +} + +func TestRound2RejectsDuplicateH1(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Clone party 2's message and set its H1 to party 0's H1. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).H1 = new(big.Int).Set(party0Content.H1) + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate h1j", 2) +} + +func TestRound2RejectsDuplicatePaillierN(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Clone party 2's message and set its PaillierPK.N to party 0's N. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).PaillierPK.N = new(big.Int).Set(party0Content.PaillierPK.N) + // Also need to update NTilde to avoid hitting "paillier N == NTilde" first + // (the original NTilde is party 2's, which is different from party 0's N). + // Actually the loop checks paillierN == NTilde within the SAME message, + // and we only changed paillierN, so NTilde is still party 2's original + // which differs from party 0's N. Should be fine. + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate modulus (Paillier N)", 2) +} + +func TestRound2RejectsDuplicateNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Clone party 2's message and set its NTilde to party 0's NTilde. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).NTilde = new(big.Int).Set(party0Content.NTilde) + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate modulus (NTilde)", 2) +} + +// TestRound2RejectsCrossDuplicateH1H2 verifies that the shared h1H2Map +// catches the case where party A's H1 equals party B's H2. +func TestRound2RejectsCrossDuplicateH1H2(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Set party 2's H1 to party 0's H2. Since party 0 is processed first, + // its H2 is already in the shared map when party 2's H1 is checked. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).H1 = new(big.Int).Set(party0Content.H2) + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate h1j", 2) +} + +// TestRound2RejectsCrossPartyPaillierNEqualsNTilde verifies that the merged +// modulusMap catches the case where Party A's PaillierN equals Party B's NTilde +// (cross-party collision). This prevents an attacker who knows the factorization +// of their own Paillier N from forging range proofs against another party's +// auxiliary modulus. +func TestRound2RejectsCrossPartyPaillierNEqualsNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Set party 2's PaillierPK.N to party 0's NTilde. Party 0 is processed + // first, so its NTilde is already in the modulusMap when party 2's + // PaillierN is checked. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).PaillierPK.N = new(big.Int).Set(party0Content.NTilde) + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate modulus (Paillier N)", 2) +} + +// TestRound2RejectsCrossPartyNTildeEqualsPaillierN verifies the reverse +// direction: Party A's NTilde equals Party B's PaillierN. +func TestRound2RejectsCrossPartyNTildeEqualsPaillierN(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + // Set party 2's NTilde to party 0's PaillierN. + bad := cloneR1MsgContent(msgs[2]) + party0Content := msgs[0].Content.(*KGRound1Message) + bad.Content.(*KGRound1Message).NTilde = new(big.Int).Set(party0Content.PaillierPK.N) + msgs[2] = bad + expectRound2Error(t, fix, msgs, "duplicate modulus (NTilde)", 2) +} + +// TestRound2RejectsOversizedPaillierN verifies that the != 2048 check +// rejects oversized N (not just undersized). +func TestRound2RejectsOversizedPaillierN(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + n := bad.Content.(*KGRound1Message).PaillierPK.N + n.SetBit(n, 2048, 1) // set bit 2048 → 2049-bit value + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "paillier modulus insufficient bits", victimIdx) +} + +// TestRound2RejectsOversizedNTilde verifies that the != 2048 check +// rejects oversized NTilde. +func TestRound2RejectsOversizedNTilde(t *testing.T) { + fix := setupRound1ForNegativeTests(t) + msgs := cloneR1Msgs(fix.allR1) + bad := cloneR1MsgContent(msgs[victimIdx]) + nt := bad.Content.(*KGRound1Message).NTilde + nt.SetBit(nt, 2048, 1) // set bit 2048 → 2049-bit value + msgs[victimIdx] = bad + expectRound2Error(t, fix, msgs, "NTildej insufficient bits", victimIdx) +} diff --git a/tss-lib/ecdsa/keygen/round3_negative_test.go b/tss-lib/ecdsa/keygen/round3_negative_test.go new file mode 100644 index 0000000..5f91104 --- /dev/null +++ b/tss-lib/ecdsa/keygen/round3_negative_test.go @@ -0,0 +1,341 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +const ( + negN = 3 + negThreshold = 1 // 2-of-3 +) + +// round3TestFixture holds all state needed to call Round3 for a single +// party (party 0) with valid Round2 messages from the other parties. +type round3TestFixture struct { + states []*KeygenState + allR2P2P [][]*tss.Message // allR2P2P[receiver][sender] + allR2Bcast []*tss.Message // allR2Bcast[sender] +} + +// setupRound3Fixture runs Round1 + Round2 for a 3-party keygen and +// returns a fixture whose allR2P2P and allR2Bcast are valid messages +// ready for Round3. The caller can corrupt individual messages before +// invoking Round3. +func setupRound3Fixture(t *testing.T) *round3TestFixture { + t.Helper() + + preParams := loadTestPreParams(t, negN) + + pIDs := tss.GenerateTestPartyIDs(negN) + peerCtx := tss.NewPeerContext(pIDs) + + // -- Round 1 -- + states := make([]*KeygenState, negN) + allR1 := make([]*tss.Message, negN) + for i := 0; i < negN; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], negN, negThreshold) + st, out, err := Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + allR1[i] = out.Messages[0] + } + + // -- Round 2 -- + r2Outputs := make([]*RoundOutput, negN) + for i := 0; i < negN; i++ { + out, err := Round2(context.Background(), states[i], allR1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + r2Outputs[i] = out + } + + // Route Round2 messages. + allR2P2P := make([][]*tss.Message, negN) + allR2Bcast := make([]*tss.Message, negN) + for i := 0; i < negN; i++ { + allR2P2P[i] = make([]*tss.Message, negN) + } + for sender := 0; sender < negN; sender++ { + for _, msg := range r2Outputs[sender].Messages { + if msg.To == nil { + allR2Bcast[sender] = msg + } else { + for _, to := range msg.To { + allR2P2P[to.Index][sender] = msg + } + } + } + // Own P2P and broadcast self-messages from state. + allR2P2P[sender][sender] = states[sender].ExportR2P2PSelf() + if allR2Bcast[sender] == nil { + allR2Bcast[sender] = states[sender].ExportR2BcastSelf() + } + } + + return &round3TestFixture{ + states: states, + allR2P2P: allR2P2P, + allR2Bcast: allR2Bcast, + } +} + +// cloneP2PMsg creates a shallow copy of a P2P message with a cloned +// KGRound2Message1 content, so mutations do not affect the original. +func cloneP2PMsg(orig *tss.Message) *tss.Message { + content := orig.Content.(*KGRound2Message1) + cloned := &KGRound2Message1{ + Share: new(big.Int).Set(content.Share), + FacProof: content.FacProof, + ReceiverID: make([]byte, len(content.ReceiverID)), + } + copy(cloned.ReceiverID, content.ReceiverID) + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: cloned, + } +} + +// cloneBcastMsg creates a shallow copy of a broadcast message with a +// cloned KGRound2Message2 content. +func cloneBcastMsg(orig *tss.Message) *tss.Message { + content := orig.Content.(*KGRound2Message2) + dcmt := make([]*big.Int, len(content.DeCommitment)) + for i, v := range content.DeCommitment { + if v != nil { + dcmt[i] = new(big.Int).Set(v) + } + } + cloned := &KGRound2Message2{ + DeCommitment: dcmt, + ModProof: content.ModProof, + } + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: cloned, + } +} + +// copyP2PSlice returns a deep copy of a []*tss.Message slice for P2P +// messages targeting a single receiver. +func copyP2PSlice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneP2PMsg(m) + } + } + return out +} + +// copyBcastSlice returns a deep copy of the broadcast message slice. +func copyBcastSlice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneBcastMsg(m) + } + } + return out +} + +// requireRound3Error calls Round3 for party 0 and asserts that it +// returns an error containing the expected substring and identifies +// the correct culprit party. +func requireRound3Error(t *testing.T, fix *round3TestFixture, p2p []*tss.Message, bcast []*tss.Message, wantSubstr string, wantCulpritIdx int) { + t.Helper() + _, err := Round3(context.Background(), fix.states[0], p2p, bcast) + if err == nil { + t.Fatalf("expected Round3 to fail with %q, but it succeeded", wantSubstr) + } + if !strings.Contains(err.Error(), wantSubstr) { + t.Fatalf("expected error containing %q, got: %v", wantSubstr, err) + } + var tssErr *tss.Error + if ok := isError(err, &tssErr); !ok { + t.Fatal("expected a *tss.Error with culprit information") + } + culprits := tssErr.Culprits() + if len(culprits) != 1 || culprits[0].Index != wantCulpritIdx { + t.Fatalf("expected culprit index %d, got: %v", wantCulpritIdx, culprits) + } +} + +// --------------------------------------------------------------------------- +// Test 1: ReceiverID mismatch +// --------------------------------------------------------------------------- + +func TestRound3RejectsReceiverIDMismatch(t *testing.T) { + fix := setupRound3Fixture(t) + + // Tamper: change sender 1's P2P ReceiverID to garbage. + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + content := p2p[1].Content.(*KGRound2Message1) + content.ReceiverID = []byte("wrong-receiver-id") + + requireRound3Error(t, fix, p2p, bcast, "receiverId mismatch", 1) +} + +// --------------------------------------------------------------------------- +// Test 2: Bad decommitment +// --------------------------------------------------------------------------- + +func TestRound3RejectsBadDeCommitment(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + // Corrupt one element of sender 1's decommitment. + content := bcast[1].Content.(*KGRound2Message2) + if len(content.DeCommitment) > 1 { + content.DeCommitment[1] = new(big.Int).Add(content.DeCommitment[1], big.NewInt(1)) + } else { + t.Fatal("decommitment too short to corrupt") + } + + requireRound3Error(t, fix, p2p, bcast, "de-commitment verify failed", 1) +} + +// --------------------------------------------------------------------------- +// Test 3: Nil ModProof (proofs enabled) +// --------------------------------------------------------------------------- + +func TestRound3RejectsNilModProof(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + // Set sender 1's ModProof to nil. + content := bcast[1].Content.(*KGRound2Message2) + content.ModProof = nil + + requireRound3Error(t, fix, p2p, bcast, "modProof missing", 1) +} + +// --------------------------------------------------------------------------- +// Test 4: Bad ModProof (corrupted W) +// --------------------------------------------------------------------------- + +func TestRound3RejectsBadModProof(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + // Corrupt the W field of sender 1's ModProof. + content := bcast[1].Content.(*KGRound2Message2) + corrupted := &modproof.ProofMod{ + W: new(big.Int).Add(content.ModProof.W, big.NewInt(1)), + A: content.ModProof.A, + B: content.ModProof.B, + } + corrupted.X = content.ModProof.X + corrupted.Z = content.ModProof.Z + content.ModProof = corrupted + + requireRound3Error(t, fix, p2p, bcast, "modProof verify failed", 1) +} + +// --------------------------------------------------------------------------- +// Test 5: Nil FacProof (proofs enabled) +// --------------------------------------------------------------------------- + +func TestRound3RejectsNilFacProof(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + // Set sender 1's FacProof to nil. + content := p2p[1].Content.(*KGRound2Message1) + content.FacProof = nil + + requireRound3Error(t, fix, p2p, bcast, "facProof missing", 1) +} + +// --------------------------------------------------------------------------- +// Test 6: Bad FacProof (corrupted P field) +// --------------------------------------------------------------------------- + +func TestRound3RejectsBadFacProof(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + // Corrupt the P field of sender 1's FacProof. + content := p2p[1].Content.(*KGRound2Message1) + orig := content.FacProof + content.FacProof = &facproof.ProofFac{ + P: new(big.Int).Add(orig.P, big.NewInt(1)), + Q: orig.Q, + A: orig.A, + B: orig.B, + T: orig.T, + Sigma: orig.Sigma, + Z1: orig.Z1, + Z2: orig.Z2, + W1: orig.W1, + W2: orig.W2, + V: orig.V, + } + + requireRound3Error(t, fix, p2p, bcast, "facProof verify failed", 1) +} + +// --------------------------------------------------------------------------- +// Test 7: Bad VSS share +// --------------------------------------------------------------------------- + +func TestRound3RejectsBadVSSShare(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + // Corrupt the VSS share from sender 1. + content := p2p[1].Content.(*KGRound2Message1) + content.Share = new(big.Int).Add(content.Share, big.NewInt(1)) + + requireRound3Error(t, fix, p2p, bcast, "vss verify failed", 1) +} + +// TestRound3RejectsContextCancellation verifies that Round3 returns +// a context error when the context is pre-cancelled. +func TestRound3RejectsContextCancellation(t *testing.T) { + fix := setupRound3Fixture(t) + + p2p := copyP2PSlice(fix.allR2P2P[0]) + bcast := copyBcastSlice(fix.allR2Bcast) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() // pre-cancel + + _, err := Round3(ctx, fix.states[0], p2p, bcast) + if err == nil { + t.Fatal("expected Round3 to fail with cancelled context") + } + if !strings.Contains(err.Error(), "context canceled") { + t.Fatalf("expected 'context canceled' error, got: %v", err) + } +} diff --git a/tss-lib/ecdsa/keygen/round4_negative_test.go b/tss-lib/ecdsa/keygen/round4_negative_test.go new file mode 100644 index 0000000..78bdaf6 --- /dev/null +++ b/tss-lib/ecdsa/keygen/round4_negative_test.go @@ -0,0 +1,262 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "context" + "errors" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// fullKeygenFixture holds state after running rounds 1-3 for all n parties, +// with all expensive proofs disabled (DLN, MOD, FAC) for test speed. +// The caller can corrupt allR3 entries before calling Round4. +type fullKeygenFixture struct { + states []*KeygenState + allR3 []*tss.Message // allR3[j] = party j's round 3 broadcast + n int +} + +// setupRound1Through3 runs a complete 3-party keygen through rounds 1-3 +// with all proof flags disabled. Returns a fixture ready for Round4. +func setupRound1Through3(t *testing.T) *fullKeygenFixture { + t.Helper() + const n = 3 + const threshold = 1 // 2-of-3 + + preParams := loadTestPreParams(t, n) + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + // -- Round 1 -- + states := make([]*KeygenState, n) + allR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + allR1[i] = out.Messages[0] + } + + // -- Round 2 -- + r2P2P := make([][]*tss.Message, n) + r2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + r2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := Round2(context.Background(), states[i], allR1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2Bcast[i] = msg + } else { + for _, to := range msg.To { + r2P2P[to.Index][i] = msg + } + } + } + r2P2P[i][i] = states[i].ExportR2P2PSelf() + if r2Bcast[i] == nil { + r2Bcast[i] = states[i].ExportR2BcastSelf() + } + } + + // -- Round 3 -- + allR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := Round3(context.Background(), states[i], r2P2P[i], r2Bcast) + if err != nil { + t.Fatalf("Round3[%d]: %v", i, err) + } + allR3[i] = out.Messages[0] + } + + return &fullKeygenFixture{ + states: states, + allR3: allR3, + n: n, + } +} + +// TestRound4RejectsBadPaillierProof runs rounds 1-3 honestly, then +// corrupts party 1's Paillier proof in the round 3 message and +// asserts that Round4 (run by party 0) returns a "paillier verify +// failed" error with party 1 identified as the culprit. +func TestRound4RejectsBadPaillierProof(t *testing.T) { + fix := setupRound1Through3(t) + + // Corrupt party 1's Paillier proof: replace each proof element + // with a random big.Int that will not satisfy pi^N == xi mod N. + corruptIdx := 1 + msgs := make([]*tss.Message, fix.n) + copy(msgs, fix.allR3) + + origMsg := msgs[corruptIdx] + origContent := origMsg.Content.(*KGRound3Message) + + // Create a corrupted proof by flipping bits in each element. + var badProof paillier.Proof + for i := 0; i < paillier.ProofIters; i++ { + if origContent.PaillierProof[i] != nil { + corrupted := new(big.Int).Set(origContent.PaillierProof[i]) + corrupted.Add(corrupted, big.NewInt(1)) // shift by 1 to break the proof + badProof[i] = corrupted + } else { + badProof[i] = big.NewInt(42) + } + } + + msgs[corruptIdx] = &tss.Message{ + From: origMsg.From, + IsBroadcast: true, + Content: &KGRound3Message{ + PaillierProof: badProof, + }, + } + + // Run Round4 as party 0. + _, err := Round4(context.Background(), fix.states[0], msgs) + if err == nil { + t.Fatal("expected Round4 to reject corrupted Paillier proof, got nil error") + } + if !strings.Contains(err.Error(), "paillier verify failed") { + t.Fatalf("expected 'paillier verify failed' error, got: %v", err) + } + + // Verify the culprit is party 1. + var tssErr *tss.Error + if ok := isError(err, &tssErr); !ok { + t.Fatal("expected a *tss.Error with culprit information") + } + culprits := tssErr.Culprits() + if len(culprits) == 0 { + t.Fatal("expected at least one culprit in the error") + } + foundCulprit := false + for _, c := range culprits { + if c.Index == corruptIdx { + foundCulprit = true + break + } + } + if !foundCulprit { + t.Fatalf("expected party %d as culprit, got culprits: %v", corruptIdx, culprits) + } +} + +// TestRound4RejectsAllNilPaillierProof verifies that Round4 rejects a +// Paillier proof where all elements are nil (malformed message). +func TestRound4RejectsAllNilPaillierProof(t *testing.T) { + fix := setupRound1Through3(t) + + corruptIdx := 1 + msgs := make([]*tss.Message, fix.n) + copy(msgs, fix.allR3) + + origMsg := msgs[corruptIdx] + + // All-nil proof elements. + var nilProof paillier.Proof // zero value: all nils + + msgs[corruptIdx] = &tss.Message{ + From: origMsg.From, + IsBroadcast: true, + Content: &KGRound3Message{ + PaillierProof: nilProof, + }, + } + + _, err := Round4(context.Background(), fix.states[0], msgs) + if err == nil { + t.Fatal("expected Round4 to reject all-nil Paillier proof, got nil error") + } + // The error may be "paillier verify failed" (culprit error) or contain + // an inner error about nil proof elements from paillier.Proof.Verify. + if !strings.Contains(err.Error(), "paillier") { + t.Fatalf("expected paillier-related error, got: %v", err) + } + + // Verify the culprit is party 1 (corruptIdx). + var tssErr *tss.Error + if ok := isError(err, &tssErr); !ok { + t.Fatal("expected a *tss.Error with culprit information") + } + culprits := tssErr.Culprits() + if len(culprits) == 0 { + t.Fatal("expected at least one culprit in the error") + } + foundCulprit := false + for _, c := range culprits { + if c.Index == corruptIdx { + foundCulprit = true + break + } + } + if !foundCulprit { + t.Fatalf("expected party %d as culprit, got culprits: %v", corruptIdx, culprits) + } +} + +// TestRound4ContextCancellation verifies that Round4 respects context +// cancellation and returns the context error. +func TestRound4ContextCancellation(t *testing.T) { + fix := setupRound1Through3(t) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() // pre-cancel + + _, err := Round4(ctx, fix.states[0], fix.allR3) + if err == nil { + t.Fatal("expected error from cancelled context, got nil") + } + if !strings.Contains(err.Error(), "context canceled") { + t.Fatalf("expected 'context canceled' error, got: %v", err) + } +} + +// TestRound4HonestPassesForAllParties is a positive sanity check: +// after an honest round 1-3, Round4 should succeed for every party. +func TestRound4HonestPassesForAllParties(t *testing.T) { + fix := setupRound1Through3(t) + + for i := 0; i < fix.n; i++ { + out, err := Round4(context.Background(), fix.states[i], fix.allR3) + if err != nil { + t.Fatalf("Round4[%d]: %v", i, err) + } + if out.Save == nil { + t.Fatalf("Round4[%d]: Save is nil", i) + } + if out.Save.ECDSAPub == nil { + t.Fatalf("Round4[%d]: ECDSAPub is nil", i) + } + } +} + +// isError is a helper that unwraps err to a *tss.Error via direct type assertion. +func isError(err error, target interface{}) bool { + tssErr := &tss.Error{} + ok := errors.As(err, &tssErr) + if ok { + *(target.(**tss.Error)) = tssErr + return true + } + return false +} diff --git a/tss-lib/ecdsa/keygen/round_1.go b/tss-lib/ecdsa/keygen/round_1.go deleted file mode 100644 index df28231..0000000 --- a/tss-lib/ecdsa/keygen/round_1.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "context" - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmts "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -var zero = big.NewInt(0) - -// round 1 represents round 1 of the keygen part of the GG18 ECDSA TSS spec (Gennaro, Goldfeder; 2018) -func newRound1(params *tss.Parameters, save *LocalPartySaveData, temp *localTempData, out chan<- tss.Message, end chan<- *LocalPartySaveData) tss.Round { - return &round1{ - &base{params, save, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 1}, - } -} - -func (round *round1) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 1 - round.started = true - round.resetOK() - - Pi := round.PartyID() - i := Pi.Index - - // 1. calculate "partial" key share ui - ui := common.GetRandomPositiveInt(round.PartialKeyRand(), round.EC().Params().N) - - round.temp.ui = ui - - // 2. compute the vss shares - ids := round.Parties().IDs().Keys() - vs, shares, err := vss.Create(round.EC(), round.Threshold(), ui, ids, round.Rand()) - if err != nil { - return round.WrapError(err, Pi) - } - round.save.Ks = ids - - // security: the original u_i may be discarded - ui = zero // clears the secret data from memory - _ = ui // silences a linter warning - - // make commitment -> (C, D) - pGFlat, err := crypto.FlattenECPoints(vs) - if err != nil { - return round.WrapError(err, Pi) - } - cmt := cmts.NewHashCommitment(round.Rand(), pGFlat...) - - // 4. generate Paillier public key E_i, private key and proof - // 5-7. generate safe primes for ZKPs used later on - // 9-11. compute ntilde, h1, h2 (uses safe primes) - // use the pre-params if they were provided to the LocalParty constructor - var preParams *LocalPreParams - if round.save.LocalPreParams.Validate() && !round.save.LocalPreParams.ValidateWithProof() { - return round.WrapError( - errors.New("`optionalPreParams` failed to validate; it might have been generated with an older version of tss-lib")) - } else if round.save.LocalPreParams.ValidateWithProof() { - preParams = &round.save.LocalPreParams - } else { - { - ctx, cancel := context.WithTimeout(context.Background(), round.SafePrimeGenTimeout()) - defer cancel() - preParams, err = GeneratePreParamsWithContextAndRandom(ctx, round.Rand(), round.Concurrency()) - if err != nil { - return round.WrapError(errors.New("pre-params generation failed"), Pi) - } - } - } - round.save.LocalPreParams = *preParams - round.save.NTildej[i] = preParams.NTildei - round.save.H1j[i], round.save.H2j[i] = preParams.H1i, preParams.H2i - - // generate the dlnproofs for keygen - h1i, h2i, alpha, beta, p, q, NTildei := preParams.H1i, - preParams.H2i, - preParams.Alpha, - preParams.Beta, - preParams.P, - preParams.Q, - preParams.NTildei - dlnProof1 := dlnproof.NewDLNProof(h1i, h2i, alpha, p, q, NTildei, round.Rand()) - dlnProof2 := dlnproof.NewDLNProof(h2i, h1i, beta, p, q, NTildei, round.Rand()) - - // for this P: SAVE - // - shareID - // and keep in temporary storage: - // - VSS Vs - // - our set of Shamir shares - round.temp.ssidNonce = new(big.Int).SetUint64(0) - round.save.ShareID = ids[i] - round.temp.vs = vs - ssid, err := round.getSSID() - if err != nil { - return round.WrapError(errors.New("failed to generate ssid")) - } - round.temp.ssid = ssid - round.temp.shares = shares - - // for this P: SAVE de-commitments, paillier keys for round 2 - round.save.PaillierSK = preParams.PaillierSK - round.save.PaillierPKs[i] = &preParams.PaillierSK.PublicKey - round.temp.deCommitPolyG = cmt.D - - // BROADCAST commitments, paillier pk + proof; round 1 message - { - msg, err := NewKGRound1Message( - round.PartyID(), cmt.C, &preParams.PaillierSK.PublicKey, preParams.NTildei, preParams.H1i, preParams.H2i, dlnProof1, dlnProof2) - if err != nil { - return round.WrapError(err, Pi) - } - round.temp.kgRound1Messages[i] = msg - round.out <- msg - } - return nil -} - -func (round *round1) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*KGRound1Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round1) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.kgRound1Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - // vss check is in round 2 - round.ok[j] = true - } - return ret, nil -} - -func (round *round1) NextRound() tss.Round { - round.started = false - return &round2{round} -} diff --git a/tss-lib/ecdsa/keygen/round_2.go b/tss-lib/ecdsa/keygen/round_2.go deleted file mode 100644 index b855d9e..0000000 --- a/tss-lib/ecdsa/keygen/round_2.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "encoding/hex" - "errors" - "math/big" - "sync" - - "github.com/hemilabs/x/tss-lib/v2/crypto/facproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/modproof" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - paillierBitsLen = 2048 -) - -func (round *round2) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 2 - round.started = true - round.resetOK() - - common.Logger.Debugf( - "%s Setting up DLN verification with concurrency level of %d", - round.PartyID(), - round.Concurrency(), - ) - dlnVerifier := NewDlnProofVerifier(round.Concurrency()) - - i := round.PartyID().Index - - // 6. verify dln proofs, store r1 message pieces, ensure uniqueness of h1j, h2j - h1H2Map := make(map[string]struct{}, len(round.temp.kgRound1Messages)*2) - dlnProof1FailCulprits := make([]*tss.PartyID, len(round.temp.kgRound1Messages)) - dlnProof2FailCulprits := make([]*tss.PartyID, len(round.temp.kgRound1Messages)) - wg := new(sync.WaitGroup) - for j, msg := range round.temp.kgRound1Messages { - r1msg := msg.Content().(*KGRound1Message) - H1j, H2j, NTildej, paillierPKj := r1msg.UnmarshalH1(), - r1msg.UnmarshalH2(), - r1msg.UnmarshalNTilde(), - r1msg.UnmarshalPaillierPK() - if paillierPKj.N.BitLen() != paillierBitsLen { - return round.WrapError(errors.New("got paillier modulus with insufficient bits for this party"), msg.GetFrom()) - } - if H1j.Cmp(H2j) == 0 { - return round.WrapError(errors.New("h1j and h2j were equal for this party"), msg.GetFrom()) - } - if NTildej.BitLen() != paillierBitsLen { - return round.WrapError(errors.New("got NTildej with insufficient bits for this party"), msg.GetFrom()) - } - h1JHex, h2JHex := hex.EncodeToString(H1j.Bytes()), hex.EncodeToString(H2j.Bytes()) - if _, found := h1H2Map[h1JHex]; found { - return round.WrapError(errors.New("this h1j was already used by another party"), msg.GetFrom()) - } - if _, found := h1H2Map[h2JHex]; found { - return round.WrapError(errors.New("this h2j was already used by another party"), msg.GetFrom()) - } - h1H2Map[h1JHex], h1H2Map[h2JHex] = struct{}{}, struct{}{} - - wg.Add(2) - _j := j - _msg := msg - - dlnVerifier.VerifyDLNProof1(r1msg, H1j, H2j, NTildej, func(isValid bool) { - if !isValid { - dlnProof1FailCulprits[_j] = _msg.GetFrom() - } - wg.Done() - }) - dlnVerifier.VerifyDLNProof2(r1msg, H2j, H1j, NTildej, func(isValid bool) { - if !isValid { - dlnProof2FailCulprits[_j] = _msg.GetFrom() - } - wg.Done() - }) - } - wg.Wait() - for _, culprit := range append(dlnProof1FailCulprits, dlnProof2FailCulprits...) { - if culprit != nil { - return round.WrapError(errors.New("dln proof verification failed"), culprit) - } - } - // save NTilde_j, h1_j, h2_j, ... - for j, msg := range round.temp.kgRound1Messages { - if j == i { - continue - } - r1msg := msg.Content().(*KGRound1Message) - paillierPK, H1j, H2j, NTildej, KGC := r1msg.UnmarshalPaillierPK(), - r1msg.UnmarshalH1(), - r1msg.UnmarshalH2(), - r1msg.UnmarshalNTilde(), - r1msg.UnmarshalCommitment() - round.save.PaillierPKs[j] = paillierPK // used in round 4 - round.save.NTildej[j] = NTildej - round.save.H1j[j], round.save.H2j[j] = H1j, H2j - round.temp.KGCs[j] = KGC - } - - // 5. p2p send share ij to Pj - shares := round.temp.shares - ContextI := append(round.temp.ssid, big.NewInt(int64(i)).Bytes()...) - for j, Pj := range round.Parties().IDs() { - - facProof := &facproof.ProofFac{ - P: zero, Q: zero, A: zero, B: zero, T: zero, Sigma: zero, - Z1: zero, Z2: zero, W1: zero, W2: zero, V: zero, - } - if !round.Params().NoProofFac() { - var err error - facProof, err = facproof.NewProof(ContextI, round.EC(), round.save.PaillierSK.N, round.save.NTildej[j], - round.save.H1j[j], round.save.H2j[j], round.save.PaillierSK.P, round.save.PaillierSK.Q, round.Rand()) - if err != nil { - return round.WrapError(err, round.PartyID()) - } - - } - r2msg1 := NewKGRound2Message1(Pj, round.PartyID(), shares[j], facProof) - // do not send to this Pj, but store for round 3 - if j == i { - round.temp.kgRound2Message1s[j] = r2msg1 - continue - } - round.out <- r2msg1 - } - - // 7. BROADCAST de-commitments of Shamir poly*G - modProof := &modproof.ProofMod{W: zero, X: *new([80]*big.Int), A: zero, B: zero, Z: *new([80]*big.Int)} - if !round.Parameters.NoProofMod() { - var err error - modProof, err = modproof.NewProof(ContextI, round.save.PaillierSK.N, - round.save.PaillierSK.P, round.save.PaillierSK.Q, round.Rand()) - if err != nil { - return round.WrapError(err, round.PartyID()) - } - } - r2msg2 := NewKGRound2Message2(round.PartyID(), round.temp.deCommitPolyG, modProof) - round.temp.kgRound2Message2s[i] = r2msg2 - round.out <- r2msg2 - - return nil -} - -func (round *round2) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*KGRound2Message1); ok { - return !msg.IsBroadcast() - } - if _, ok := msg.Content().(*KGRound2Message2); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round2) Update() (bool, *tss.Error) { - // guard - VERIFY de-commit for all Pj - ret := true - for j, msg := range round.temp.kgRound2Message1s { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - msg2 := round.temp.kgRound2Message2s[j] - if msg2 == nil || !round.CanAccept(msg2) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round2) NextRound() tss.Round { - round.started = false - return &round3{round} -} diff --git a/tss-lib/ecdsa/keygen/round_3.go b/tss-lib/ecdsa/keygen/round_3.go deleted file mode 100644 index d4f5063..0000000 --- a/tss-lib/ecdsa/keygen/round_3.go +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - "math/big" - - "github.com/hashicorp/go-multierror" - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round3) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 3 - round.started = true - round.resetOK() - - Ps := round.Parties().IDs() - PIdx := round.PartyID().Index - - // 1,9. calculate xi - xi := new(big.Int).Set(round.temp.shares[PIdx].Share) - for j := range Ps { - if j == PIdx { - continue - } - r2msg1 := round.temp.kgRound2Message1s[j].Content().(*KGRound2Message1) - share := r2msg1.UnmarshalShare() - xi = new(big.Int).Add(xi, share) - } - round.save.Xi = new(big.Int).Mod(xi, round.Params().EC().Params().N) - - // 2-3. - Vc := make(vss.Vs, round.Threshold()+1) - for c := range Vc { - Vc[c] = round.temp.vs[c] // ours - } - - // 4-11. - type vssOut struct { - unWrappedErr error - pjVs vss.Vs - } - chs := make([]chan vssOut, len(Ps)) - for i := range chs { - if i == PIdx { - continue - } - chs[i] = make(chan vssOut) - } - for j := range Ps { - if j == PIdx { - continue - } - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - // 6-8. - go func(j int, ch chan<- vssOut) { - // 4-9. - KGCj := round.temp.KGCs[j] - r2msg2 := round.temp.kgRound2Message2s[j].Content().(*KGRound2Message2) - KGDj := r2msg2.UnmarshalDeCommitment() - cmtDeCmt := commitments.HashCommitDecommit{C: KGCj, D: KGDj} - ok, flatPolyGs := cmtDeCmt.DeCommit() - if !ok || flatPolyGs == nil { - ch <- vssOut{errors.New("de-commitment verify failed"), nil} - return - } - PjVs, err := crypto.UnFlattenECPoints(round.Params().EC(), flatPolyGs) - if err != nil { - ch <- vssOut{err, nil} - return - } - modProof, err := r2msg2.UnmarshalModProof() - if err != nil && round.Parameters.NoProofMod() { - // For old parties, the modProof could be not exist - // Not return error for compatibility reason - common.Logger.Warningf("modProof not exist:%s", Ps[j]) - } else { - if err != nil { - ch <- vssOut{errors.New("modProof verify failed"), nil} - return - } - if ok = modProof.Verify(ContextJ, round.save.PaillierPKs[j].N); !ok { - ch <- vssOut{errors.New("modProof verify failed"), nil} - return - } - } - r2msg1 := round.temp.kgRound2Message1s[j].Content().(*KGRound2Message1) - PjShare := vss.Share{ - Threshold: round.Threshold(), - ID: round.PartyID().KeyInt(), - Share: r2msg1.UnmarshalShare(), - } - if ok = PjShare.Verify(round.Params().EC(), round.Threshold(), PjVs); !ok { - ch <- vssOut{errors.New("vss verify failed"), nil} - return - } - facProof, err := r2msg1.UnmarshalFacProof() - if err != nil && round.NoProofFac() { - // For old parties, the facProof could be not exist - // Not return error for compatibility reason - common.Logger.Warningf("facProof not exist:%s", Ps[j]) - } else { - if err != nil { - ch <- vssOut{errors.New("facProof verify failed"), nil} - return - } - if ok = facProof.Verify(ContextJ, round.EC(), round.save.PaillierPKs[j].N, round.save.NTildei, - round.save.H1i, round.save.H2i); !ok { - ch <- vssOut{errors.New("facProof verify failed"), nil} - return - } - } - - // (9) handled above - ch <- vssOut{nil, PjVs} - }(j, chs[j]) - } - - // consume unbuffered channels (end the goroutines) - vssResults := make([]vssOut, len(Ps)) - { - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - for j, Pj := range Ps { - if j == PIdx { - continue - } - vssResults[j] = <-chs[j] - // collect culprits to error out with - if err := vssResults[j].unWrappedErr; err != nil { - culprits = append(culprits, Pj) - } - } - var multiErr error - if len(culprits) > 0 { - for _, vssResult := range vssResults { - if vssResult.unWrappedErr != nil { - multiErr = multierror.Append(multiErr, vssResult.unWrappedErr) - } - } - return round.WrapError(multiErr, culprits...) - } - } - { - var err error - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - for j, Pj := range Ps { - if j == PIdx { - continue - } - // 10-11. - PjVs := vssResults[j].pjVs - for c := 0; c <= round.Threshold(); c++ { - Vc[c], err = Vc[c].Add(PjVs[c]) - if err != nil { - culprits = append(culprits, Pj) - } - } - } - if len(culprits) > 0 { - return round.WrapError(errors.New("adding PjVs[c] to Vc[c] resulted in a point not on the curve"), culprits...) - } - } - - // 12-16. compute Xj for each Pj - { - var err error - modQ := common.ModInt(round.Params().EC().Params().N) - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - bigXj := round.save.BigXj - for j := 0; j < round.PartyCount(); j++ { - Pj := round.Parties().IDs()[j] - kj := Pj.KeyInt() - BigXj := Vc[0] - z := new(big.Int).SetInt64(int64(1)) - for c := 1; c <= round.Threshold(); c++ { - z = modQ.Mul(z, kj) - BigXj, err = BigXj.Add(Vc[c].ScalarMult(z)) - if err != nil { - culprits = append(culprits, Pj) - } - } - bigXj[j] = BigXj - } - if len(culprits) > 0 { - return round.WrapError(errors.New("adding Vc[c].ScalarMult(z) to BigXj resulted in a point not on the curve"), culprits...) - } - round.save.BigXj = bigXj - } - - // 17. compute and SAVE the ECDSA public key `y` - ecdsaPubKey, err := crypto.NewECPoint(round.Params().EC(), Vc[0].X(), Vc[0].Y()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "public key is not on the curve")) - } - round.save.ECDSAPub = ecdsaPubKey - - // PRINT public key & private share - common.Logger.Debugf("%s public key: %x", round.PartyID(), ecdsaPubKey) - - // BROADCAST paillier proof for Pi - ki := round.PartyID().KeyInt() - proof := round.save.PaillierSK.Proof(ki, ecdsaPubKey) - r3msg := NewKGRound3Message(round.PartyID(), proof) - round.temp.kgRound3Messages[PIdx] = r3msg - round.out <- r3msg - return nil -} - -func (round *round3) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*KGRound3Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round3) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.kgRound3Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - // proof check is in round 4 - round.ok[j] = true - } - return ret, nil -} - -func (round *round3) NextRound() tss.Round { - round.started = false - return &round4{round} -} diff --git a/tss-lib/ecdsa/keygen/round_4.go b/tss-lib/ecdsa/keygen/round_4.go deleted file mode 100644 index 3a89a9c..0000000 --- a/tss-lib/ecdsa/keygen/round_4.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round4) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 4 - round.started = true - round.resetOK() - - i := round.PartyID().Index - Ps := round.Parties().IDs() - PIDs := Ps.Keys() - ecdsaPub := round.save.ECDSAPub - - // 1-3. (concurrent) - // r3 messages are assumed to be available and != nil in this function - r3msgs := round.temp.kgRound3Messages - chs := make([]chan bool, len(r3msgs)) - for i := range chs { - chs[i] = make(chan bool) - } - for j, msg := range round.temp.kgRound3Messages { - if j == i { - continue - } - r3msg := msg.Content().(*KGRound3Message) - go func(prf paillier.Proof, j int, ch chan<- bool) { - ppk := round.save.PaillierPKs[j] - ok, err := prf.Verify(ppk.N, PIDs[j], ecdsaPub) - if err != nil { - common.Logger.Error(round.WrapError(err, Ps[j]).Error()) - ch <- false - return - } - ch <- ok - }(r3msg.UnmarshalProofInts(), j, chs[j]) - } - - // consume unbuffered channels (end the goroutines) - for j, ch := range chs { - if j == i { - round.ok[j] = true - continue - } - round.ok[j] = <-ch - } - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - for j, ok := range round.ok { - if !ok { - culprits = append(culprits, Ps[j]) - common.Logger.Warningf("paillier verify failed for party %s", Ps[j]) - continue - } - common.Logger.Debugf("paillier verify passed for party %s", Ps[j]) - - } - if len(culprits) > 0 { - return round.WrapError(errors.New("paillier verify failed"), culprits...) - } - - round.end <- round.save - - return nil -} - -func (round *round4) CanAccept(msg tss.ParsedMessage) bool { - // not expecting any incoming messages in this round - return false -} - -func (round *round4) Update() (bool, *tss.Error) { - // not expecting any incoming messages in this round - return false, nil -} - -func (round *round4) NextRound() tss.Round { - return nil // finished! -} diff --git a/tss-lib/ecdsa/keygen/round_fn.go b/tss-lib/ecdsa/keygen/round_fn.go new file mode 100644 index 0000000..9cdbd66 --- /dev/null +++ b/tss-lib/ecdsa/keygen/round_fn.go @@ -0,0 +1,619 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "math/big" + "sync" + + "github.com/hashicorp/go-multierror" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmts "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// getSSID computes the SSID for a given round number using the state's +// params and temp data. Same hash as base.getSSID but without the +// round-method receiver. +func getSSID(params *tss.Parameters, temp *localTempData, roundNumber int) ([]byte, error) { + ssidList := []*big.Int{ + new(big.Int).SetBytes([]byte("ecdsa-keygen")), + params.EC().Params().P, params.EC().Params().N, + params.EC().Params().B, params.EC().Params().Gx, + params.EC().Params().Gy, + } + ssidList = append(ssidList, params.Parties().IDs().Keys()...) + ssidList = append(ssidList, big.NewInt(int64(params.PartyCount()))) + ssidList = append(ssidList, big.NewInt(int64(params.Threshold()))) + ssidList = append(ssidList, big.NewInt(int64(roundNumber))) + ssidList = append(ssidList, temp.ssidNonce) + if cid := params.CeremonyID(); len(cid) > 0 { + ssidList = append(ssidList, new(big.Int).SetBytes(cid)) + } + ssid := common.SHA512_256i(ssidList...).Bytes() + return ssid, nil +} + +// Round1 initializes keygen state, generates the VSS shares and +// commitment, and produces the round 1 broadcast message. +// +// ctx is used when preParams are absent and safe primes must be +// generated (slow — several seconds). When valid preParams are +// provided, ctx is unused. +// +// preParams must be pre-generated and validated via +// GeneratePreParams / ValidateWithProof. If preParams is zero-value +// (Validate() returns false), Round1 generates fresh safe primes. +func Round1(ctx context.Context, params *tss.Parameters, preParams LocalPreParams) (*KeygenState, *RoundOutput, error) { + partyCount := params.PartyCount() + save := NewLocalPartySaveData(partyCount) + temp := &localTempData{ + localMessageStore: localMessageStore{ + kgRound1Messages: make([]*tss.Message, partyCount), + kgRound2Message1s: make([]*tss.Message, partyCount), + kgRound2Message2s: make([]*tss.Message, partyCount), + kgRound3Messages: make([]*tss.Message, partyCount), + }, + KGCs: make([]cmts.HashCommitment, partyCount), + } + + Pi := params.PartyID() + i := Pi.Index + + // 1. calculate "partial" key share ui + ui := common.GetRandomPositiveInt(params.PartialKeyRand(), params.EC().Params().N) + temp.ui = ui + + // 2. compute the vss shares + ids := params.Parties().IDs().Keys() + vs, shares, poly, err := vss.Create(params.EC(), params.Threshold(), ui, ids, params.Rand()) + if err != nil { + return nil, nil, err + } + temp.Poly = poly + save.Ks = ids + + // Clear ui after last use. + temp.ui = new(big.Int) + + // make commitment -> (C, D) + pGFlat, err := crypto.FlattenECPoints(vs) + if err != nil { + return nil, nil, err + } + cmt := cmts.NewHashCommitment(params.Rand(), pGFlat...) + + // Paillier key and safe primes + var pp *LocalPreParams + if preParams.Validate() && !preParams.ValidateWithProof() { + return nil, nil, errors.New("preParams failed validation (may be from older tss-lib version)") + } else if preParams.ValidateWithProof() { + pp = &preParams + } else { + ctx, cancel := context.WithTimeout(ctx, params.SafePrimeGenTimeout()) + defer cancel() + pp, err = GeneratePreParamsWithContextAndRandom(ctx, params.Rand(), params.Concurrency()) + if err != nil { + return nil, nil, errors.New("pre-params generation failed") + } + } + save.LocalPreParams = *pp + save.NTildej[i] = pp.NTildei + save.H1j[i], save.H2j[i] = pp.H1i, pp.H2i + + temp.ssidNonce = new(big.Int).SetUint64(uint64(params.SSIDNonce())) + save.ShareID = ids[i] + temp.vs = vs + ssid, err := getSSID(params, temp, 1) + if err != nil { + return nil, nil, errors.New("failed to generate ssid") + } + temp.ssid = ssid + temp.shares = shares + + // DLN proofs (gated by NoProofDLN for SNARK mode) + var dlnProof1, dlnProof2 *dlnproof.Proof + if !params.NoProofDLN() { + h1i, h2i, alpha, beta := pp.H1i, pp.H2i, pp.Alpha, pp.Beta + p, q, NTildei := pp.P, pp.Q, pp.NTildei + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(i))) + dlnProof1 = dlnproof.NewDLNProof(ContextI, h1i, h2i, alpha, p, q, NTildei, params.Rand()) + dlnProof2 = dlnproof.NewDLNProof(ContextI, h2i, h1i, beta, p, q, NTildei, params.Rand()) + } + + save.PaillierSK = pp.PaillierSK + save.PaillierPKs[i] = &pp.PaillierSK.PublicKey + temp.deCommitPolyG = cmt.D + + msg := NewKGRound1Message( + Pi, cmt.C, &pp.PaillierSK.PublicKey, + pp.NTildei, pp.H1i, pp.H2i, + dlnProof1, dlnProof2) + // Store own round 1 message so round 2 can validate uniformly. + temp.kgRound1Messages[i] = msg + + state := &KeygenState{params: params, save: &save, temp: temp} + out := &RoundOutput{ + Messages: []*tss.Message{msg}, + Poly: poly, + } + return state, out, nil +} + +// Round2 validates round 1 messages (DLN proofs, parameter checks), +// generates VSS shares for each party, and produces P2P + broadcast +// messages. +// +// r1Msgs must be indexed by party: r1Msgs[j] is party j's +// KGRound1Message broadcast. r1Msgs[i] (own message from Round1) +// must be present. +func Round2(ctx context.Context, state *KeygenState, r1Msgs []*tss.Message) (*RoundOutput, error) { + params := state.params + save := state.save + temp := state.temp + + // Populate temp message store so validation code reads from it. + tss.MergeMsgs(temp.kgRound1Messages, r1Msgs) + + i := params.PartyID().Index + + dlnVerifier := NewDlnProofVerifier(params.Concurrency()) + + // Comprehensive parameter validation battery. + h1H2Map := make(map[string]struct{}, len(r1Msgs)*2) + // Single modulus map for both PaillierN and NTilde: catches cross-party + // collisions (e.g., Party A's PaillierN == Party B's NTilde) that separate + // maps would miss. Such a collision lets A forge range proofs against B. + modulusMap := make(map[string]struct{}, len(r1Msgs)*2) + dlnProof1FailCulprits := make([]*tss.PartyID, len(r1Msgs)) + dlnProof2FailCulprits := make([]*tss.PartyID, len(r1Msgs)) + wg := new(sync.WaitGroup) + for j, msg := range r1Msgs { + r1msg := msg.Content.(*KGRound1Message) + H1j, H2j, NTildej, paillierPKj := r1msg.H1, + r1msg.H2, + r1msg.NTilde, + r1msg.PaillierPK + if paillierPKj.N.BitLen() != paillierBitsLen { + return nil, tss.NewError(errors.New("paillier modulus insufficient bits"), TaskName, 2, params.PartyID(), msg.From) + } + if paillierPKj.N.Bit(0) == 0 { + return nil, tss.NewError(errors.New("even paillier modulus"), TaskName, 2, params.PartyID(), msg.From) + } + if paillierPKj.N.ProbablyPrime(20) { + return nil, tss.NewError(errors.New("prime paillier modulus"), TaskName, 2, params.PartyID(), msg.From) + } + sqrtN := new(big.Int).Sqrt(paillierPKj.N) + if new(big.Int).Mul(sqrtN, sqrtN).Cmp(paillierPKj.N) == 0 { + return nil, tss.NewError(errors.New("perfect-square paillier modulus"), TaskName, 2, params.PartyID(), msg.From) + } + if H1j.Cmp(H2j) == 0 { + return nil, tss.NewError(errors.New("h1j == h2j"), TaskName, 2, params.PartyID(), msg.From) + } + if H1j.Cmp(big.NewInt(1)) == 0 || H2j.Cmp(big.NewInt(1)) == 0 { + return nil, tss.NewError(errors.New("h1j or h2j is 1"), TaskName, 2, params.PartyID(), msg.From) + } + if NTildej.BitLen() != paillierBitsLen { + return nil, tss.NewError(errors.New("NTildej insufficient bits"), TaskName, 2, params.PartyID(), msg.From) + } + if NTildej.Bit(0) == 0 { + return nil, tss.NewError(errors.New("even NTildej"), TaskName, 2, params.PartyID(), msg.From) + } + if NTildej.ProbablyPrime(20) { + return nil, tss.NewError(errors.New("prime NTildej"), TaskName, 2, params.PartyID(), msg.From) + } + sqrtNT := new(big.Int).Sqrt(NTildej) + if new(big.Int).Mul(sqrtNT, sqrtNT).Cmp(NTildej) == 0 { + return nil, tss.NewError(errors.New("perfect-square NTildej"), TaskName, 2, params.PartyID(), msg.From) + } + if paillierPKj.N.Cmp(NTildej) == 0 { + return nil, tss.NewError(errors.New("paillier N == NTilde"), TaskName, 2, params.PartyID(), msg.From) + } + if new(big.Int).GCD(nil, nil, H1j, NTildej).Cmp(big.NewInt(1)) != 0 { + return nil, tss.NewError(errors.New("h1j not coprime with NTildej"), TaskName, 2, params.PartyID(), msg.From) + } + if new(big.Int).GCD(nil, nil, H2j, NTildej).Cmp(big.NewInt(1)) != 0 { + return nil, tss.NewError(errors.New("h2j not coprime with NTildej"), TaskName, 2, params.PartyID(), msg.From) + } + h1JHex, h2JHex := hex.EncodeToString(H1j.Bytes()), hex.EncodeToString(H2j.Bytes()) + if _, found := h1H2Map[h1JHex]; found { + return nil, tss.NewError(errors.New("duplicate h1j"), TaskName, 2, params.PartyID(), msg.From) + } + if _, found := h1H2Map[h2JHex]; found { + return nil, tss.NewError(errors.New("duplicate h2j"), TaskName, 2, params.PartyID(), msg.From) + } + h1H2Map[h1JHex], h1H2Map[h2JHex] = struct{}{}, struct{}{} + paillierNHex := hex.EncodeToString(paillierPKj.N.Bytes()) + if _, found := modulusMap[paillierNHex]; found { + return nil, tss.NewError(errors.New("duplicate modulus (Paillier N)"), TaskName, 2, params.PartyID(), msg.From) + } + modulusMap[paillierNHex] = struct{}{} + nTildeHex := hex.EncodeToString(NTildej.Bytes()) + if _, found := modulusMap[nTildeHex]; found { + return nil, tss.NewError(errors.New("duplicate modulus (NTilde)"), TaskName, 2, params.PartyID(), msg.From) + } + modulusMap[nTildeHex] = struct{}{} + + if !params.NoProofDLN() { + wg.Add(2) + _j := j + _msg := msg + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + dlnVerifier.VerifyDLNProof(r1msg.DLNProof1, ContextJ, H1j, H2j, NTildej, func(isValid bool) { + if !isValid { + dlnProof1FailCulprits[_j] = _msg.From + } + wg.Done() + }) + dlnVerifier.VerifyDLNProof(r1msg.DLNProof2, ContextJ, H2j, H1j, NTildej, func(isValid bool) { + if !isValid { + dlnProof2FailCulprits[_j] = _msg.From + } + wg.Done() + }) + } + } + wg.Wait() + if err := ctx.Err(); err != nil { + return nil, err + } + for _, culprits := range [][]*tss.PartyID{dlnProof1FailCulprits, dlnProof2FailCulprits} { + for _, culprit := range culprits { + if culprit != nil { + return nil, tss.NewError(errors.New("dln proof verification failed"), TaskName, 2, params.PartyID(), culprit) + } + } + } + + // Save NTilde_j, h1_j, h2_j, PaillierPKs, KGCs + for j, msg := range r1Msgs { + if j == i { + continue + } + r1msg := msg.Content.(*KGRound1Message) + save.PaillierPKs[j] = r1msg.PaillierPK + save.NTildej[j] = r1msg.NTilde + save.H1j[j] = r1msg.H1 + save.H2j[j] = r1msg.H2 + temp.KGCs[j] = r1msg.Commitment + } + + // P2P send share ij to Pj + out := &RoundOutput{} + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(i))) + for j, Pj := range params.Parties().IDs() { + var facProofObj *facproof.ProofFac + if !params.NoProofFac() { + var err error + facProofObj, err = facproof.NewProof(ContextI, params.EC(), save.PaillierSK.N, + save.NTildej[j], save.H1j[j], save.H2j[j], + save.PaillierSK.P, save.PaillierSK.Q, params.Rand()) + if err != nil { + return nil, fmt.Errorf("round 2 fac proof for party %d: %w", j, err) + } + } + r2msg1 := NewKGRound2Message1(Pj, params.PartyID(), temp.shares[j], facProofObj) + if j == i { + temp.kgRound2Message1s[j] = r2msg1 + continue + } + out.Messages = append(out.Messages, r2msg1) + } + + // BROADCAST de-commitments + var modProofObj *modproof.ProofMod + if !params.NoProofMod() { + var err error + modProofObj, err = modproof.NewProof(ContextI, save.PaillierSK.N, + save.PaillierSK.P, save.PaillierSK.Q, params.Rand()) + if err != nil { + return nil, fmt.Errorf("round 2 mod proof: %w", err) + } + } + r2msg2 := NewKGRound2Message2(params.PartyID(), temp.deCommitPolyG, modProofObj) + temp.kgRound2Message2s[i] = r2msg2 + out.Messages = append(out.Messages, r2msg2) + + return out, nil +} + +// Round3 validates round 2 messages (de-commitments, VSS shares, +// FacProof, ModProof, ReceiverID), computes the aggregate public +// key and per-party public key shares, and produces the round 3 +// Paillier proof broadcast. +// +// r2p2p[j] is party j's KGRound2Message1 (P2P, contains VSS share). +// r2bcast[j] is party j's KGRound2Message2 (broadcast, contains +// de-commitment and ModProof). +func Round3(ctx context.Context, state *KeygenState, r2p2p, r2bcast []*tss.Message) (*RoundOutput, error) { + params := state.params + save := state.save + temp := state.temp + Ps := params.Parties().IDs() + PIdx := params.PartyID().Index + + // Store own messages + tss.MergeMsgs(temp.kgRound2Message1s, r2p2p) + tss.MergeMsgs(temp.kgRound2Message2s, r2bcast) + + // 1,9. calculate xi + xi := new(big.Int).Set(temp.shares[PIdx].Share) + for j := range Ps { + if j == PIdx { + continue + } + r2msg1 := r2p2p[j].Content.(*KGRound2Message1) + share := r2msg1.Share + xi = new(big.Int).Add(xi, share) + } + save.Xi = new(big.Int).Mod(xi, params.EC().Params().N) + if save.Xi.Sign() == 0 { + return nil, errors.New("xi is zero") + } + + // 2-3. + Vc := make(vss.Vs, params.Threshold()+1) + for c := range Vc { + Vc[c] = temp.vs[c] + } + + // 4-11. Concurrent VSS/proof verification + type vssOut struct { + unWrappedErr error + pjVs vss.Vs + } + vssResults := make([]vssOut, len(Ps)) + gctx, gcancel := context.WithCancel(ctx) + defer gcancel() + wg := sync.WaitGroup{} + for j := range Ps { + if j == PIdx { + continue + } + wg.Add(1) + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + go func(j int) { + defer wg.Done() + if gctx.Err() != nil { + return + } + KGCj := temp.KGCs[j] + r2msg2 := r2bcast[j].Content.(*KGRound2Message2) + KGDj := r2msg2.DeCommitment + cmtDeCmt := cmts.HashCommitDecommit{C: KGCj, D: KGDj} + ok, flatPolyGs := cmtDeCmt.DeCommit() + if !ok || flatPolyGs == nil { + vssResults[j] = vssOut{errors.New("de-commitment verify failed"), nil} + gcancel() + return + } + PjVs, err := crypto.UnFlattenECPoints(params.EC(), flatPolyGs) + if err != nil { + vssResults[j] = vssOut{err, nil} + gcancel() + return + } + if gctx.Err() != nil { + return + } + if !params.NoProofMod() { + if r2msg2.ModProof == nil { + vssResults[j] = vssOut{errors.New("modProof missing"), nil} + gcancel() + return + } + if ok = r2msg2.ModProof.Verify(ContextJ, save.PaillierPKs[j].N); !ok { + vssResults[j] = vssOut{errors.New("modProof verify failed"), nil} + gcancel() + return + } + } + if gctx.Err() != nil { + return + } + r2msg1 := r2p2p[j].Content.(*KGRound2Message1) + myKey := params.PartyID().KeyInt().Bytes() + if !bytes.Equal(r2msg1.ReceiverID, myKey) { + vssResults[j] = vssOut{errors.New("receiverId mismatch"), nil} + gcancel() + return + } + PjShare := vss.Share{ + Threshold: params.Threshold(), + ID: params.PartyID().KeyInt(), + Share: r2msg1.Share, + } + if ok = PjShare.Verify(params.EC(), params.Threshold(), PjVs); !ok { + vssResults[j] = vssOut{errors.New("vss verify failed"), nil} + gcancel() + return + } + if gctx.Err() != nil { + return + } + if !params.NoProofFac() { + if r2msg1.FacProof == nil { + vssResults[j] = vssOut{errors.New("facProof missing"), nil} + gcancel() + return + } + if ok = r2msg1.FacProof.Verify(ContextJ, params.EC(), save.PaillierPKs[j].N, + save.NTildei, save.H1i, save.H2i); !ok { + vssResults[j] = vssOut{errors.New("facProof verify failed"), nil} + gcancel() + return + } + } + vssResults[j] = vssOut{nil, PjVs} + }(j) + } + wg.Wait() + + if err := ctx.Err(); err != nil { + return nil, err + } + + // Collect results + { + culprits := make([]*tss.PartyID, 0, len(Ps)) + for j, Pj := range Ps { + if j == PIdx { + continue + } + if err := vssResults[j].unWrappedErr; err != nil { + culprits = append(culprits, Pj) + } + } + if len(culprits) > 0 { + var multiErr error + for _, vssResult := range vssResults { + if vssResult.unWrappedErr != nil { + multiErr = multierror.Append(multiErr, vssResult.unWrappedErr) + } + } + return nil, tss.NewError(multiErr, TaskName, 3, params.PartyID(), culprits...) + } + } + { + var err error + culprits := make([]*tss.PartyID, 0, len(Ps)) + for j, Pj := range Ps { + if j == PIdx { + continue + } + PjVs := vssResults[j].pjVs + for c := 0; c <= params.Threshold(); c++ { + Vc[c], err = Vc[c].Add(PjVs[c]) + if err != nil { + culprits = append(culprits, Pj) + } + } + } + if len(culprits) > 0 { + return nil, tss.NewError(errors.New("vc point addition failed"), TaskName, 3, params.PartyID(), culprits...) + } + } + + // 12-16. compute Xj for each Pj + { + var err error + modQ := common.ModInt(params.EC().Params().N) + culprits := make([]*tss.PartyID, 0, len(Ps)) + bigXj := save.BigXj + for j := 0; j < params.PartyCount(); j++ { + Pj := Ps[j] + kj := Pj.KeyInt() + BigXj := Vc[0] + z := new(big.Int).SetInt64(1) + for c := 1; c <= params.Threshold(); c++ { + z = modQ.Mul(z, kj) + BigXj, err = BigXj.Add(Vc[c].ScalarMult(z)) + if err != nil { + culprits = append(culprits, Pj) + } + } + if BigXj.IsIdentity() { + culprits = append(culprits, Pj) + } else { + bigXj[j] = BigXj + } + } + if len(culprits) > 0 { + return nil, tss.NewError(errors.New("BigXj identity or computation error"), TaskName, 3, params.PartyID(), culprits...) + } + save.BigXj = bigXj + } + + // 17. compute and SAVE the ECDSA public key + ecdsaPubKey, err := crypto.NewECPoint(params.EC(), Vc[0].X(), Vc[0].Y()) + if err != nil { + return nil, fmt.Errorf("round 4 ecdsa pubkey: %w", err) + } + if ecdsaPubKey.IsIdentity() { + return nil, errors.New("public key is the identity point") + } + save.ECDSAPub = ecdsaPubKey + + // BROADCAST paillier proof + ki := params.PartyID().KeyInt() + proof := save.PaillierSK.Proof(ki, ecdsaPubKey) + r3msg := NewKGRound3Message(params.PartyID(), proof) + + return &RoundOutput{Messages: []*tss.Message{r3msg}}, nil +} + +// Round4 verifies round 3 Paillier proofs and returns the final +// key share data. +// +// r3Msgs[j] is party j's KGRound3Message broadcast containing the +// Paillier proof. +func Round4(ctx context.Context, state *KeygenState, r3Msgs []*tss.Message) (*RoundOutput, error) { + params := state.params + save := state.save + + i := params.PartyID().Index + Ps := params.Parties().IDs() + PIDs := Ps.Keys() + ecdsaPub := save.ECDSAPub + + // Concurrent Paillier proof verification + ok := make([]bool, len(Ps)) + ok[i] = true // self + gctx, gcancel := context.WithCancel(ctx) + defer gcancel() + wg := sync.WaitGroup{} + for j, msg := range r3Msgs { + if j == i { + continue + } + wg.Add(1) + r3msg := msg.Content.(*KGRound3Message) + go func(prf paillier.Proof, j int) { + defer wg.Done() + if gctx.Err() != nil { + return + } + ppk := save.PaillierPKs[j] + verified, err := prf.Verify(ppk.N, PIDs[j], ecdsaPub) + if err != nil { + common.Logger.Error(err) + gcancel() + return + } + ok[j] = verified + if !verified { + gcancel() + } + }(r3msg.PaillierProof, j) + } + wg.Wait() + if err := ctx.Err(); err != nil { + return nil, err + } + culprits := make([]*tss.PartyID, 0, len(Ps)) + for j, v := range ok { + if !v { + culprits = append(culprits, Ps[j]) + } + } + if len(culprits) > 0 { + return nil, tss.NewError(errors.New("paillier verify failed"), TaskName, 4, params.PartyID(), culprits...) + } + + return &RoundOutput{Save: save}, nil +} diff --git a/tss-lib/ecdsa/keygen/round_fn_test.go b/tss-lib/ecdsa/keygen/round_fn_test.go new file mode 100644 index 0000000..20f6ea1 --- /dev/null +++ b/tss-lib/ecdsa/keygen/round_fn_test.go @@ -0,0 +1,247 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "context" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestRoundFnKeygenThreeParties runs a 3-party keygen using the pure +// round functions (no channels, no goroutines). Verifies that the +// produced key shares are valid: Xi*G == BigXj[ownIndex] (Feldman +// invariant) and all parties agree on the same ECDSAPub. +func TestRoundFnKeygenThreeParties(t *testing.T) { + const n = 3 + const threshold = 1 // 2-of-3 + + preParams := loadTestPreParams(t, n) + + // Generate sorted party IDs. + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + // -- Round 1 -- + states := make([]*KeygenState, n) + r1Outputs := make([]*RoundOutput, n) + r1Msgs := make([][]*tss.Message, n) // r1Msgs[i] = party i's broadcasts + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + r1Outputs[i] = out + r1Msgs[i] = make([]*tss.Message, 1) // Round1 produces 1 broadcast + r1Msgs[i][0] = out.Messages[0] + } + if r1Outputs[0].Poly == nil { + t.Fatal("Round1 should return Poly for SNARK witness") + } + + // Collect round 1 broadcasts: allR1[j] = party j's broadcast + allR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + allR1[i] = r1Outputs[i].Messages[0] + } + + // -- Round 2 -- + r2Outputs := make([]*RoundOutput, n) + for i := 0; i < n; i++ { + out, err := Round2(context.Background(), states[i], allR1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + r2Outputs[i] = out + } + + // Collect round 2 messages per party. + // Round2 produces: (n-1) P2P messages + 1 broadcast. + // P2P messages have GetTo() != nil; broadcast has GetTo() == nil. + allR2P2P := make([][]*tss.Message, n) // allR2P2P[receiver][sender] + allR2Bcast := make([]*tss.Message, n) // allR2Bcast[sender] + for i := 0; i < n; i++ { + allR2P2P[i] = make([]*tss.Message, n) + } + for sender := 0; sender < n; sender++ { + for _, msg := range r2Outputs[sender].Messages { + pm := msg + if pm.To == nil { + // broadcast + allR2Bcast[sender] = pm + } else { + // P2P — route to recipient + for _, to := range pm.To { + allR2P2P[to.Index][sender] = pm + } + } + } + // Own P2P message to self is in state.temp + allR2P2P[sender][sender] = states[sender].temp.kgRound2Message1s[sender] + } + // Fill own broadcast + for i := 0; i < n; i++ { + allR2Bcast[i] = states[i].temp.kgRound2Message2s[i] + if allR2Bcast[i] == nil { + allR2Bcast[i] = r2Outputs[i].Messages[len(r2Outputs[i].Messages)-1] + } + } + + // -- Round 3 -- + r3Outputs := make([]*RoundOutput, n) + for i := 0; i < n; i++ { + out, err := Round3(context.Background(), states[i], allR2P2P[i], allR2Bcast) + if err != nil { + t.Fatalf("Round3[%d]: %v", i, err) + } + r3Outputs[i] = out + } + + // Collect round 3 broadcasts + allR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + allR3[i] = r3Outputs[i].Messages[0] + } + + // -- Round 4 -- + saves := make([]*LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := Round4(context.Background(), states[i], allR3) + if err != nil { + t.Fatalf("Round4[%d]: %v", i, err) + } + if out.Save == nil { + t.Fatalf("Round4[%d]: Save is nil", i) + } + saves[i] = out.Save + } + + // -- Verify -- + // 1. All parties agree on ECDSAPub + for i := 1; i < n; i++ { + if saves[i].ECDSAPub.X().Cmp(saves[0].ECDSAPub.X()) != 0 || + saves[i].ECDSAPub.Y().Cmp(saves[0].ECDSAPub.Y()) != 0 { + t.Fatalf("party %d has different ECDSAPub", i) + } + } + + // 2. Feldman invariant: Xi * G == BigXj[ownIndex] + curve := tss.S256() + for i := 0; i < n; i++ { + xi := saves[i].Xi + gx, gy := curve.ScalarBaseMult(xi.Bytes()) + bxj := saves[i].BigXj[i] + if gx.Cmp(bxj.X()) != 0 || gy.Cmp(bxj.Y()) != 0 { + t.Fatalf("party %d: Xi*G != BigXj[%d]", i, i) + } + } + + // 3. Lagrange interpolation of Xi recovers the private key. + // sk = sum_i(Xi * lambda_i) where lambda_i = prod_{j!=i}(kj/(kj-ki)) + q := curve.Params().N + sk := new(big.Int) + for i := 0; i < n; i++ { + li := new(big.Int).SetInt64(1) + ki := saves[i].ShareID + for j := 0; j < n; j++ { + if j == i { + continue + } + kj := saves[j].ShareID + num := new(big.Int).Set(kj) + den := new(big.Int).Sub(kj, ki) + den.Mod(den, q) + den.ModInverse(den, q) + li.Mul(li, num) + li.Mul(li, den) + li.Mod(li, q) + } + term := new(big.Int).Mul(saves[i].Xi, li) + sk.Add(sk, term) + } + sk.Mod(sk, q) + pubX, pubY := curve.ScalarBaseMult(sk.Bytes()) + if pubX.Cmp(saves[0].ECDSAPub.X()) != 0 || pubY.Cmp(saves[0].ECDSAPub.Y()) != 0 { + t.Fatal("Lagrange interpolation of Xi does not match ECDSAPub") + } + + t.Logf("keygen succeeded: ECDSAPub = (%x, %x)", saves[0].ECDSAPub.X(), saves[0].ECDSAPub.Y()) +} + +// TestRoundFnKeygenNoProofFlags exercises keygen with all proof +// generation/verification disabled (SNARK mode). +func TestRoundFnKeygenNoProofFlags(t *testing.T) { + const n = 3 + const threshold = 1 + + preParams := loadTestPreParams(t, n) + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states := make([]*KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + params.SetNoProofMod() + params.SetNoProofFac() + params.SetNoProofDLN() + st, out, err := Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2P2P := make([][]*tss.Message, n) + r2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + r2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := Round2(context.Background(), states[i], r1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + r2Bcast[i] = pm + } else { + for _, to := range pm.To { + r2P2P[to.Index][i] = pm + } + } + } + r2P2P[i][i] = states[i].ExportR2P2PSelf() + if r2Bcast[i] == nil { + r2Bcast[i] = states[i].ExportR2BcastSelf() + } + } + + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := Round3(context.Background(), states[i], r2P2P[i], r2Bcast) + if err != nil { + t.Fatalf("Round3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + + for i := 0; i < n; i++ { + out, err := Round4(context.Background(), states[i], r3) + if err != nil { + t.Fatalf("Round4[%d]: %v", i, err) + } + if out.Save == nil { + t.Fatalf("Round4[%d]: Save is nil", i) + } + } + t.Log("keygen with all proofs disabled: passed") +} diff --git a/tss-lib/ecdsa/keygen/round_state.go b/tss-lib/ecdsa/keygen/round_state.go new file mode 100644 index 0000000..973abc0 --- /dev/null +++ b/tss-lib/ecdsa/keygen/round_state.go @@ -0,0 +1,50 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// KeygenState holds all mutable state between keygen rounds. +// Opaque to the caller — pass between round functions without +// reading or modifying. +type KeygenState struct { + params *tss.Parameters + save *LocalPartySaveData + temp *localTempData +} + +// RoundOutput holds the outbound messages and artifacts produced +// by a single round function. +type RoundOutput struct { + // Messages to send to other parties. Broadcast messages + // have GetTo() == nil; P2P messages have one recipient. + Messages []*tss.Message + + // Save is non-nil only on the final round (Round4). + // Contains the complete key share data. + Save *LocalPartySaveData + + // Poly contains the VSS polynomial coefficients for SNARK + // witness extraction. Non-nil only on Round1. + Poly []*big.Int +} + +// ExportR2P2PSelf returns this party's own Round2 P2P message (stored +// during Round2 for self-delivery). Needed by the signing test to +// build the full message matrix without channels. +func (s *KeygenState) ExportR2P2PSelf() *tss.Message { + i := s.params.PartyID().Index + return s.temp.kgRound2Message1s[i] +} + +// ExportR2BcastSelf returns this party's own Round2 broadcast message. +func (s *KeygenState) ExportR2BcastSelf() *tss.Message { + i := s.params.PartyID().Index + return s.temp.kgRound2Message2s[i] +} diff --git a/tss-lib/ecdsa/keygen/rounds.go b/tss-lib/ecdsa/keygen/rounds.go deleted file mode 100644 index e4949b5..0000000 --- a/tss-lib/ecdsa/keygen/rounds.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - TaskName = "ecdsa-keygen" -) - -type ( - base struct { - *tss.Parameters - save *LocalPartySaveData - temp *localTempData - out chan<- tss.Message - end chan<- *LocalPartySaveData - ok []bool // `ok` tracks parties which have been verified by Update() - started bool - number int - } - round1 struct { - *base - } - round2 struct { - *round1 - } - round3 struct { - *round2 - } - round4 struct { - *round3 - } -) - -var ( - _ tss.Round = (*round1)(nil) - _ tss.Round = (*round2)(nil) - _ tss.Round = (*round3)(nil) - _ tss.Round = (*round4)(nil) -) - -// ----- // - -func (round *base) Params() *tss.Parameters { - return round.Parameters -} - -func (round *base) RoundNumber() int { - return round.number -} - -// CanProceed is inherited by other rounds -func (round *base) CanProceed() bool { - if !round.started { - return false - } - for _, ok := range round.ok { - if !ok { - return false - } - } - return true -} - -// WaitingFor is called by a Party for reporting back to the caller -func (round *base) WaitingFor() []*tss.PartyID { - Ps := round.Parties().IDs() - ids := make([]*tss.PartyID, 0, len(round.ok)) - for j, ok := range round.ok { - if ok { - continue - } - ids = append(ids, Ps[j]) - } - return ids -} - -func (round *base) WrapError(err error, culprits ...*tss.PartyID) *tss.Error { - return tss.NewError(err, TaskName, round.number, round.PartyID(), culprits...) -} - -// ----- // - -// `ok` tracks parties which have been verified by Update() -func (round *base) resetOK() { - for j := range round.ok { - round.ok[j] = false - } -} - -// get ssid from local params -func (round *base) getSSID() ([]byte, error) { - ssidList := []*big.Int{round.EC().Params().P, round.EC().Params().N, round.EC().Params().Gx, round.EC().Params().Gy} // ec curve - ssidList = append(ssidList, round.Parties().IDs().Keys()...) - ssidList = append(ssidList, big.NewInt(int64(round.number))) // round number - ssidList = append(ssidList, round.temp.ssidNonce) - ssid := common.SHA512_256i(ssidList...).Bytes() - - return ssid, nil -} diff --git a/tss-lib/ecdsa/keygen/save_data.go b/tss-lib/ecdsa/keygen/save_data.go index 4e48c23..740ecba 100644 --- a/tss-lib/ecdsa/keygen/save_data.go +++ b/tss-lib/ecdsa/keygen/save_data.go @@ -1,19 +1,19 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen import ( "encoding/hex" "errors" + "fmt" "math/big" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" ) type ( @@ -50,6 +50,7 @@ type ( } ) +// NewLocalPartySaveData allocates a LocalPartySaveData with slices sized for partyCount. func NewLocalPartySaveData(partyCount int) (saveData LocalPartySaveData) { saveData.Ks = make([]*big.Int, partyCount) saveData.NTildej = make([]*big.Int, partyCount) @@ -59,6 +60,7 @@ func NewLocalPartySaveData(partyCount int) (saveData LocalPartySaveData) { return } +// Validate checks that the pre-parameters are structurally valid. func (preParams LocalPreParams) Validate() bool { return preParams.PaillierSK != nil && preParams.NTildei != nil && @@ -66,14 +68,120 @@ func (preParams LocalPreParams) Validate() bool { preParams.H2i != nil } +// [FORK] ValidateWithProof: upstream only checked for nil fields. This hardened version +// adds algebraic consistency checks to verify that the pre-params are internally consistent: +// (1) NTilde = (2P+1)(2Q+1) — ensures NTilde is the product of safe primes derived from P, Q. +// (2) H2 = H1^Alpha mod NTilde — ensures the discrete-log relationship needed for DLN proofs. +// Without these checks, corrupted or tampered pre-params could silently produce invalid proofs +// that would be rejected by honest verifiers, wasting an entire keygen ceremony. func (preParams LocalPreParams) ValidateWithProof() bool { - return preParams.Validate() && + if !(preParams.Validate() && preParams.PaillierSK.P != nil && preParams.PaillierSK.Q != nil && preParams.Alpha != nil && preParams.Beta != nil && preParams.P != nil && - preParams.Q != nil + preParams.Q != nil) { + return false + } + // [FORK] Defense-in-depth: P == Q would make NTilde = (2P+1)^2, a perfect square, + // which completely breaks the DLN proof (the prover can trivially compute the order + // of (Z/NTilde·Z)*). This condition is unreachable under normal operation: P and Q + // are independently generated 1024-bit safe primes via GetRandomSafePrimesConcurrent. + // The probability of collision is ~2^{-1003}. Retained to guard against RNG failure + // or storage corruption. + if preParams.P.Cmp(preParams.Q) == 0 { + return false + } + // Verify P, Q are the Sophie Germain primes corresponding to NTilde + // should equal (2*P+1) * (2*Q+1) + safeP := new(big.Int).Mul(preParams.P, big.NewInt(2)) + safeP.Add(safeP, big.NewInt(1)) + safeQ := new(big.Int).Mul(preParams.Q, big.NewInt(2)) + safeQ.Add(safeQ, big.NewInt(1)) + expectedNTilde := new(big.Int).Mul(safeP, safeQ) + if expectedNTilde.Cmp(preParams.NTildei) != 0 { + return false + } + // Verify H2 = H1^Alpha mod NTilde + expectedH2 := new(big.Int).Exp(preParams.H1i, preParams.Alpha, preParams.NTildei) + return expectedH2.Cmp(preParams.H2i) == 0 +} + +// [FORK] ValidateSaveData performs comprehensive validation of loaded ECDSA save data, +// checking for nil fields, array consistency, curve membership of public keys, +// and the Feldman VSS invariant (Xi·G == BigXj[ownIndex]). +// +// Call this after loading save data from storage and before using it in signing +// or resharing. Without this, corrupted or tampered save data could silently produce +// invalid signatures or proofs, which would be indistinguishable from a protocol +// failure at a remote party. +// +// Returns a descriptive error or nil if all checks pass. +func (saveData LocalPartySaveData) ValidateSaveData() error { + // Secret fields. + if saveData.Xi == nil || saveData.ShareID == nil { + return errors.New("ValidateSaveData: Xi or ShareID is nil") + } + if saveData.ECDSAPub == nil { + return errors.New("ValidateSaveData: ECDSAPub is nil") + } + + // Array consistency. + n := len(saveData.Ks) + if n < 2 { + return fmt.Errorf("ValidateSaveData: party count %d is less than 2", n) + } + if len(saveData.BigXj) != n || len(saveData.NTildej) != n || + len(saveData.H1j) != n || len(saveData.H2j) != n || + len(saveData.PaillierPKs) != n { + return errors.New("ValidateSaveData: array length mismatch") + } + + // Per-party field nil checks. + for i := 0; i < n; i++ { + if saveData.Ks[i] == nil { + return fmt.Errorf("ValidateSaveData: Ks[%d] is nil", i) + } + if saveData.BigXj[i] == nil { + return fmt.Errorf("ValidateSaveData: BigXj[%d] is nil", i) + } + if !saveData.BigXj[i].IsOnCurve() { + return fmt.Errorf("ValidateSaveData: BigXj[%d] is not on curve", i) + } + if saveData.NTildej[i] == nil || saveData.H1j[i] == nil || saveData.H2j[i] == nil { + return fmt.Errorf("ValidateSaveData: NTildej/H1j/H2j[%d] is nil", i) + } + if saveData.PaillierPKs[i] == nil { + return fmt.Errorf("ValidateSaveData: PaillierPKs[%d] is nil", i) + } + } + + // Find own index from Ks using ShareID. + ownIdx := -1 + for i, k := range saveData.Ks { + if k.Cmp(saveData.ShareID) == 0 { + ownIdx = i + break + } + } + if ownIdx == -1 { + return errors.New("ValidateSaveData: ShareID not found in Ks") + } + + // Feldman VSS invariant: Xi·G must equal BigXj[ownIndex]. + // [FORK] Guard Xi=0: ScalarBaseMult(0) panics (identity point). A zero Xi means + // the party's secret share is trivially known. + if saveData.Xi.Sign() == 0 { + return errors.New("ValidateSaveData: Xi is zero") + } + ec := saveData.BigXj[ownIdx].Curve() + xiG := crypto.ScalarBaseMult(ec, saveData.Xi) + if !xiG.Equals(saveData.BigXj[ownIdx]) { + return errors.New("ValidateSaveData: Feldman VSS check failed: Xi·G != BigXj[ownIndex]") + } + + return nil } // BuildLocalSaveDataSubset re-creates the LocalPartySaveData to contain data for only the list of signing parties. diff --git a/tss-lib/ecdsa/keygen/save_data_test.go b/tss-lib/ecdsa/keygen/save_data_test.go new file mode 100644 index 0000000..650638f --- /dev/null +++ b/tss-lib/ecdsa/keygen/save_data_test.go @@ -0,0 +1,394 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// validSaveData builds a minimal LocalPartySaveData that passes +// ValidateSaveData. n=2, Xi=7, ShareID=Ks[0]. +func validSaveData(t *testing.T) LocalPartySaveData { + t.Helper() + ec := tss.S256() + xi := big.NewInt(7) + sd := NewLocalPartySaveData(2) + + sd.Xi = xi + sd.ShareID = big.NewInt(100) + + // Ks: own share ID first, then another. + sd.Ks[0] = new(big.Int).Set(sd.ShareID) + sd.Ks[1] = big.NewInt(200) + + // BigXj: own = Xi·G, other = arbitrary on-curve point. + sd.BigXj[0] = crypto.ScalarBaseMult(ec, xi) + sd.BigXj[1] = crypto.ScalarBaseMult(ec, big.NewInt(13)) + + sd.ECDSAPub = crypto.ScalarBaseMult(ec, big.NewInt(42)) + + for i := 0; i < 2; i++ { + sd.NTildej[i] = big.NewInt(int64(1000 + i)) + sd.H1j[i] = big.NewInt(int64(2000 + i)) + sd.H2j[i] = big.NewInt(int64(3000 + i)) + sd.PaillierPKs[i] = &paillier.PublicKey{N: big.NewInt(int64(4000 + i))} + } + return sd +} + +func TestValidateSaveDataHappy(t *testing.T) { + sd := validSaveData(t) + if err := sd.ValidateSaveData(); err != nil { + t.Fatalf("valid data should pass: %v", err) + } +} + +func TestValidateSaveDataNilXi(t *testing.T) { + sd := validSaveData(t) + sd.Xi = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil Xi should fail") + } +} + +func TestValidateSaveDataNilShareID(t *testing.T) { + sd := validSaveData(t) + sd.ShareID = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil ShareID should fail") + } +} + +func TestValidateSaveDataNilECDSAPub(t *testing.T) { + sd := validSaveData(t) + sd.ECDSAPub = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil ECDSAPub should fail") + } +} + +func TestValidateSaveDataTooFewParties(t *testing.T) { + sd := validSaveData(t) + sd.Ks = []*big.Int{big.NewInt(1)} + sd.BigXj = sd.BigXj[:1] + sd.NTildej = sd.NTildej[:1] + sd.H1j = sd.H1j[:1] + sd.H2j = sd.H2j[:1] + sd.PaillierPKs = sd.PaillierPKs[:1] + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("n < 2 should fail") + } +} + +func TestValidateSaveDataArrayMismatch(t *testing.T) { + sd := validSaveData(t) + sd.BigXj = sd.BigXj[:1] // length 1 vs Ks length 2 + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("array length mismatch should fail") + } +} + +func TestValidateSaveDataNilKsElement(t *testing.T) { + sd := validSaveData(t) + sd.Ks[1] = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil Ks element should fail") + } +} + +func TestValidateSaveDataNilBigXjElement(t *testing.T) { + sd := validSaveData(t) + sd.BigXj[1] = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil BigXj element should fail") + } +} + +func TestValidateSaveDataOffCurveBigXj(t *testing.T) { + sd := validSaveData(t) + sd.BigXj[1] = crypto.NewECPointNoCurveCheck(tss.S256(), big.NewInt(999), big.NewInt(999)) + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("off-curve BigXj should fail") + } +} + +func TestValidateSaveDataNilNTildej(t *testing.T) { + sd := validSaveData(t) + sd.NTildej[0] = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil NTildej should fail") + } +} + +func TestValidateSaveDataNilH1j(t *testing.T) { + sd := validSaveData(t) + sd.H1j[0] = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil H1j should fail") + } +} + +func TestValidateSaveDataNilH2j(t *testing.T) { + sd := validSaveData(t) + sd.H2j[0] = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil H2j should fail") + } +} + +func TestValidateSaveDataNilPaillierPK(t *testing.T) { + sd := validSaveData(t) + sd.PaillierPKs[0] = nil + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("nil PaillierPKs should fail") + } +} + +func TestValidateSaveDataShareIDNotInKs(t *testing.T) { + sd := validSaveData(t) + sd.ShareID = big.NewInt(999) // not in Ks + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("ShareID not in Ks should fail") + } +} + +func TestValidateSaveDataZeroXi(t *testing.T) { + sd := validSaveData(t) + sd.Xi = big.NewInt(0) + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("zero Xi should fail") + } +} + +func TestValidateSaveDataFeldmanFail(t *testing.T) { + sd := validSaveData(t) + // Xi·G won't match BigXj[0] anymore. + sd.Xi = big.NewInt(99) + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("Feldman check should fail when Xi doesn't match BigXj") + } +} + +func TestBuildLocalSaveDataSubsetSuccess(t *testing.T) { + sd := validSaveData(t) + ids := tss.GenerateTestPartyIDs(2) + // Align Ks with party keys so the lookup succeeds. + sd.Ks[0] = new(big.Int).SetBytes(ids[0].Key) + sd.Ks[1] = new(big.Int).SetBytes(ids[1].Key) + sd.ShareID = sd.Ks[0] + + // Fix BigXj[0] to match Xi·G after ShareID change. + ec := tss.S256() + sd.BigXj[0] = crypto.ScalarBaseMult(ec, sd.Xi) + + result := BuildLocalSaveDataSubset(sd, ids) + if len(result.Ks) != 2 { + t.Fatalf("expected 2 Ks, got %d", len(result.Ks)) + } + if result.Ks[0].Cmp(sd.Ks[0]) != 0 { + t.Fatal("Ks[0] mismatch") + } +} + +func TestValidatePreParamsNilFields(t *testing.T) { + pp := LocalPreParams{} + if pp.Validate() { + t.Fatal("all-nil should be invalid") + } +} + +// validPreParams builds a minimal LocalPreParams that passes ValidateWithProof +// using small safe primes. Sophie Germain primes: P=5, Q=11. +// Safe primes: safeP=2*5+1=11, safeQ=2*11+1=23. NTilde=11*23=253. +// H1=4 (=2^2 mod 253), Alpha=3, H2=H1^Alpha mod NTilde=4^3 mod 253=64. +// PaillierSK.P and PaillierSK.Q are set to dummy non-nil values (not used +// algebraically by ValidateWithProof, only nil-checked). +func validPreParams() LocalPreParams { + return LocalPreParams{ + PaillierSK: &paillier.PrivateKey{ + PublicKey: paillier.PublicKey{N: big.NewInt(1)}, + P: big.NewInt(7), + Q: big.NewInt(11), + }, + NTildei: big.NewInt(253), // 11 * 23 + H1i: big.NewInt(4), // f1^2 mod 253, f1=2 + H2i: big.NewInt(64), // 4^3 mod 253 + Alpha: big.NewInt(3), + Beta: big.NewInt(1), + P: big.NewInt(5), // Sophie Germain prime + Q: big.NewInt(11), // Sophie Germain prime + } +} + +// --- ValidateWithProof: happy path --- + +func TestValidateWithProofHappyPath(t *testing.T) { + pp := validPreParams() + if !pp.ValidateWithProof() { + t.Fatal("valid pre-params should pass ValidateWithProof") + } +} + +// --- ValidateWithProof: nil field tests (one per nil-checked field) --- + +func TestValidateWithProofNilPaillierSK(t *testing.T) { + pp := validPreParams() + pp.PaillierSK = nil + if pp.ValidateWithProof() { + t.Fatal("nil PaillierSK should be invalid") + } +} + +func TestValidateWithProofNilPaillierSKP(t *testing.T) { + pp := validPreParams() + pp.PaillierSK.P = nil + if pp.ValidateWithProof() { + t.Fatal("nil PaillierSK.P should be invalid") + } +} + +func TestValidateWithProofNilPaillierSKQ(t *testing.T) { + pp := validPreParams() + pp.PaillierSK.Q = nil + if pp.ValidateWithProof() { + t.Fatal("nil PaillierSK.Q should be invalid") + } +} + +func TestValidateWithProofNilAlpha(t *testing.T) { + pp := validPreParams() + pp.Alpha = nil + if pp.ValidateWithProof() { + t.Fatal("nil Alpha should be invalid") + } +} + +func TestValidateWithProofNilBeta(t *testing.T) { + pp := validPreParams() + pp.Beta = nil + if pp.ValidateWithProof() { + t.Fatal("nil Beta should be invalid") + } +} + +func TestValidateWithProofNilP(t *testing.T) { + pp := validPreParams() + pp.P = nil + if pp.ValidateWithProof() { + t.Fatal("nil P should be invalid") + } +} + +func TestValidateWithProofNilQ(t *testing.T) { + pp := validPreParams() + pp.Q = nil + if pp.ValidateWithProof() { + t.Fatal("nil Q should be invalid") + } +} + +func TestValidateWithProofNilNTilde(t *testing.T) { + pp := validPreParams() + pp.NTildei = nil + if pp.ValidateWithProof() { + t.Fatal("nil NTildei should be invalid") + } +} + +func TestValidateWithProofNilH1(t *testing.T) { + pp := validPreParams() + pp.H1i = nil + if pp.ValidateWithProof() { + t.Fatal("nil H1i should be invalid") + } +} + +func TestValidateWithProofNilH2(t *testing.T) { + pp := validPreParams() + pp.H2i = nil + if pp.ValidateWithProof() { + t.Fatal("nil H2i should be invalid") + } +} + +// --- ValidateWithProof: algebraic consistency tests --- + +func TestValidateWithProofPEqualsQ(t *testing.T) { + pp := validPreParams() + // Set Q = P (both = 5). To truly isolate the P==Q guard, also fix + // NTilde and H2 so the NTilde and H2 checks would PASS if the P==Q + // guard didn't exist: NTilde = (2*5+1)^2 = 121, H2 = H1^Alpha mod 121. + pp.Q = new(big.Int).Set(pp.P) // Q = 5 = P + pp.NTildei = big.NewInt(121) // (2*5+1)*(2*5+1) = 11*11 + // H2 = H1^Alpha mod NTilde = 4^3 mod 121 = 64 + pp.H2i = new(big.Int).Exp(pp.H1i, pp.Alpha, pp.NTildei) + if pp.ValidateWithProof() { + t.Fatal("P == Q should be invalid even when NTilde and H2 are consistent") + } +} + +func TestValidateWithProofBadNTilde(t *testing.T) { + pp := validPreParams() + pp.NTildei = big.NewInt(999) // wrong: expected 253 + if pp.ValidateWithProof() { + t.Fatal("wrong NTilde should be invalid") + } +} + +func TestValidateWithProofBadH2(t *testing.T) { + pp := validPreParams() + // H2 should be H1^Alpha mod NTilde = 4^3 mod 253 = 64. + // Set it to something else to trigger the final check. + pp.H2i = big.NewInt(65) + if pp.ValidateWithProof() { + t.Fatal("H2 != H1^Alpha mod NTilde should be invalid") + } +} + +// --- Validate: individual nil field tests --- + +func TestValidateNilPaillierSK(t *testing.T) { + pp := validPreParams() + pp.PaillierSK = nil + if pp.Validate() { + t.Fatal("nil PaillierSK should fail Validate") + } +} + +func TestValidateNilNTilde(t *testing.T) { + pp := validPreParams() + pp.NTildei = nil + if pp.Validate() { + t.Fatal("nil NTildei should fail Validate") + } +} + +func TestValidateNilH1(t *testing.T) { + pp := validPreParams() + pp.H1i = nil + if pp.Validate() { + t.Fatal("nil H1i should fail Validate") + } +} + +func TestValidateNilH2(t *testing.T) { + pp := validPreParams() + pp.H2i = nil + if pp.Validate() { + t.Fatal("nil H2i should fail Validate") + } +} + +func TestValidateHappyPath(t *testing.T) { + pp := validPreParams() + if !pp.Validate() { + t.Fatal("valid pre-params should pass Validate") + } +} diff --git a/tss-lib/ecdsa/keygen/ssid_test.go b/tss-lib/ecdsa/keygen/ssid_test.go new file mode 100644 index 0000000..a9e55d2 --- /dev/null +++ b/tss-lib/ecdsa/keygen/ssid_test.go @@ -0,0 +1,311 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "bytes" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// makeSSIDTestParams builds a *tss.Parameters and *localTempData suitable for +// calling getSSID. ssidNonce is set from the params' SSIDNonce (default 0). +func makeSSIDTestParams(t *testing.T, n, threshold int) (*tss.Parameters, *localTempData) { + t.Helper() + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], n, threshold) + temp := &localTempData{ + ssidNonce: new(big.Int).SetUint64(uint64(params.SSIDNonce())), + } + return params, temp +} + +// TestGetSSIDDeterministic verifies that calling getSSID twice with +// identical inputs produces the same output. +func TestGetSSIDDeterministic(t *testing.T) { + params, temp := makeSSIDTestParams(t, 3, 1) + + ssid1, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID call 1: %v", err) + } + ssid2, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID call 2: %v", err) + } + if !bytes.Equal(ssid1, ssid2) { + t.Fatalf("getSSID not deterministic: %x != %x", ssid1, ssid2) + } + if len(ssid1) == 0 { + t.Fatal("getSSID returned empty slice") + } +} + +// TestGetSSIDWithCeremonyID verifies that setting a CeremonyID changes +// the SSID output relative to no CeremonyID. +func TestGetSSIDWithCeremonyID(t *testing.T) { + params, temp := makeSSIDTestParams(t, 3, 1) + + ssidWithout, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID without CeremonyID: %v", err) + } + + params.SetCeremonyID([]byte("test-ceremony-42")) + ssidWith, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID with CeremonyID: %v", err) + } + + if bytes.Equal(ssidWithout, ssidWith) { + t.Fatal("CeremonyID did not change the SSID") + } +} + +// TestGetSSIDDifferentCeremonyIDs verifies that two distinct CeremonyIDs +// produce two distinct SSIDs. +func TestGetSSIDDifferentCeremonyIDs(t *testing.T) { + params, temp := makeSSIDTestParams(t, 3, 1) + + params.SetCeremonyID([]byte("ceremony-A")) + ssidA, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID ceremony-A: %v", err) + } + + params.SetCeremonyID([]byte("ceremony-B")) + ssidB, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID ceremony-B: %v", err) + } + + if bytes.Equal(ssidA, ssidB) { + t.Fatal("different CeremonyIDs produced the same SSID") + } +} + +// TestGetSSIDDifferentRoundNumbers verifies that same params but +// different round numbers produce different SSIDs. +func TestGetSSIDDifferentRoundNumbers(t *testing.T) { + params, temp := makeSSIDTestParams(t, 3, 1) + + ssid1, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID round 1: %v", err) + } + ssid2, err := getSSID(params, temp, 2) + if err != nil { + t.Fatalf("getSSID round 2: %v", err) + } + ssid3, err := getSSID(params, temp, 3) + if err != nil { + t.Fatalf("getSSID round 3: %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("round 1 and 2 produced the same SSID") + } + if bytes.Equal(ssid2, ssid3) { + t.Fatal("round 2 and 3 produced the same SSID") + } + if bytes.Equal(ssid1, ssid3) { + t.Fatal("round 1 and 3 produced the same SSID") + } +} + +// TestGetSSIDIncludesAllPartyKeys verifies that changing ANY party's +// key changes the SSID — not just the last party. +func TestGetSSIDIncludesAllPartyKeys(t *testing.T) { + baseKeys := []*big.Int{big.NewInt(100), big.NewInt(200), big.NewInt(300)} + + makeParams := func(k1, k2, k3 *big.Int) (*tss.Parameters, *localTempData) { + ids := tss.UnSortedPartyIDs{ + tss.NewPartyID("1", "P[1]", k1), + tss.NewPartyID("2", "P[2]", k2), + tss.NewPartyID("3", "P[3]", k3), + } + sorted := tss.SortPartyIDs(ids) + peerCtx := tss.NewPeerContext(sorted) + params := tss.NewParameters(tss.S256(), peerCtx, sorted[0], 3, 1) + temp := &localTempData{ + ssidNonce: new(big.Int).SetUint64(0), + } + return params, temp + } + + paramsOriginal, tempOriginal := makeParams(baseKeys[0], baseKeys[1], baseKeys[2]) + ssidOriginal, err := getSSID(paramsOriginal, tempOriginal, 1) + if err != nil { + t.Fatalf("getSSID original: %v", err) + } + + // Change each party's key individually and verify the SSID changes. + for i := 0; i < 3; i++ { + t.Run("change_key_"+big.NewInt(int64(i)).String(), func(t *testing.T) { + keys := []*big.Int{ + new(big.Int).Set(baseKeys[0]), + new(big.Int).Set(baseKeys[1]), + new(big.Int).Set(baseKeys[2]), + } + keys[i] = big.NewInt(999) // mutate party i's key + p, tmp := makeParams(keys[0], keys[1], keys[2]) + ssid, err := getSSID(p, tmp, 1) + if err != nil { + t.Fatalf("getSSID with changed key %d: %v", i, err) + } + if bytes.Equal(ssidOriginal, ssid) { + t.Fatalf("changing party %d's key did not change the SSID", i) + } + }) + } +} + +// TestGetSSIDIncludesNonce verifies that a different ssidNonce +// produces a different SSID. +func TestGetSSIDIncludesNonce(t *testing.T) { + params, temp0 := makeSSIDTestParams(t, 3, 1) + + ssid0, err := getSSID(params, temp0, 1) + if err != nil { + t.Fatalf("getSSID nonce=0: %v", err) + } + + temp1 := &localTempData{ + ssidNonce: big.NewInt(42), + } + ssid1, err := getSSID(params, temp1, 1) + if err != nil { + t.Fatalf("getSSID nonce=42: %v", err) + } + + if bytes.Equal(ssid0, ssid1) { + t.Fatal("different ssidNonce values produced the same SSID") + } +} + +// TestGetSSIDDifferentThreshold verifies that changing the threshold +// (e.g., 1-of-4 vs 2-of-4) changes the SSID. +func TestGetSSIDDifferentThreshold(t *testing.T) { + // Use deterministic keys so only the threshold differs. + ids := tss.UnSortedPartyIDs{ + tss.NewPartyID("1", "P", big.NewInt(101)), + tss.NewPartyID("2", "P", big.NewInt(102)), + tss.NewPartyID("3", "P", big.NewInt(103)), + tss.NewPartyID("4", "P", big.NewInt(104)), + } + sorted := tss.SortPartyIDs(ids) + peerCtx := tss.NewPeerContext(sorted) + + params1 := tss.NewParameters(tss.S256(), peerCtx, sorted[0], 4, 1) + temp1 := &localTempData{ssidNonce: new(big.Int).SetUint64(0)} + ssid1, err := getSSID(params1, temp1, 1) + if err != nil { + t.Fatalf("threshold=1: %v", err) + } + + params2 := tss.NewParameters(tss.S256(), peerCtx, sorted[0], 4, 2) + temp2 := &localTempData{ssidNonce: new(big.Int).SetUint64(0)} + ssid2, err := getSSID(params2, temp2, 1) + if err != nil { + t.Fatalf("threshold=2: %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different thresholds must produce different SSIDs") + } +} + +// TestGetSSIDDifferentPartyCount verifies that changing the party count +// (e.g., 3 parties vs 4 parties) changes the SSID. +func TestGetSSIDDifferentPartyCount(t *testing.T) { + // 3-party set + ids3 := tss.UnSortedPartyIDs{ + tss.NewPartyID("1", "P", big.NewInt(101)), + tss.NewPartyID("2", "P", big.NewInt(102)), + tss.NewPartyID("3", "P", big.NewInt(103)), + } + sorted3 := tss.SortPartyIDs(ids3) + peerCtx3 := tss.NewPeerContext(sorted3) + params3 := tss.NewParameters(tss.S256(), peerCtx3, sorted3[0], 3, 1) + temp3 := &localTempData{ssidNonce: new(big.Int).SetUint64(0)} + ssid3, err := getSSID(params3, temp3, 1) + if err != nil { + t.Fatalf("n=3: %v", err) + } + + // 4-party set (superset of the 3-party set) + ids4 := tss.UnSortedPartyIDs{ + tss.NewPartyID("1", "P", big.NewInt(101)), + tss.NewPartyID("2", "P", big.NewInt(102)), + tss.NewPartyID("3", "P", big.NewInt(103)), + tss.NewPartyID("4", "P", big.NewInt(104)), + } + sorted4 := tss.SortPartyIDs(ids4) + peerCtx4 := tss.NewPeerContext(sorted4) + params4 := tss.NewParameters(tss.S256(), peerCtx4, sorted4[0], 4, 1) + temp4 := &localTempData{ssidNonce: new(big.Int).SetUint64(0)} + ssid4, err := getSSID(params4, temp4, 1) + if err != nil { + t.Fatalf("n=4: %v", err) + } + + if bytes.Equal(ssid3, ssid4) { + t.Fatal("different party counts must produce different SSIDs") + } +} + +// TestGetSSIDDifferentCurve verifies that using a different elliptic +// curve (Edwards25519 vs secp256k1) produces a different SSID, since +// the curve parameters (P, N, B, Gx, Gy) are all hashed. +func TestGetSSIDDifferentCurve(t *testing.T) { + ids := tss.UnSortedPartyIDs{ + tss.NewPartyID("1", "P", big.NewInt(101)), + tss.NewPartyID("2", "P", big.NewInt(102)), + tss.NewPartyID("3", "P", big.NewInt(103)), + } + sorted := tss.SortPartyIDs(ids) + + peerCtx := tss.NewPeerContext(sorted) + temp := &localTempData{ssidNonce: new(big.Int).SetUint64(0)} + + paramsS256 := tss.NewParameters(tss.S256(), peerCtx, sorted[0], 3, 1) + ssidS256, err := getSSID(paramsS256, temp, 1) + if err != nil { + t.Fatalf("S256: %v", err) + } + + paramsEd := tss.NewParameters(tss.Edwards(), peerCtx, sorted[0], 3, 1) + ssidEd, err := getSSID(paramsEd, temp, 1) + if err != nil { + t.Fatalf("Edwards: %v", err) + } + + if bytes.Equal(ssidS256, ssidEd) { + t.Fatal("different curves must produce different SSIDs") + } +} + +// TestGetSSIDOutputLength verifies that getSSID produces a +// SHA-512/256 output (32 bytes). +func TestGetSSIDOutputLength(t *testing.T) { + params, temp := makeSSIDTestParams(t, 3, 1) + + ssid, err := getSSID(params, temp, 1) + if err != nil { + t.Fatalf("getSSID: %v", err) + } + // SHA-512/256 produces 32 bytes, but big.Int.Bytes() strips + // leading zeros. Verify the output is at most 32 bytes and + // non-empty. + if len(ssid) == 0 { + t.Fatal("getSSID returned empty output") + } + if len(ssid) > 32 { + t.Fatalf("getSSID output too long: %d bytes (expected <= 32)", len(ssid)) + } +} diff --git a/tss-lib/ecdsa/keygen/test_utils.go b/tss-lib/ecdsa/keygen/test_utils.go deleted file mode 100644 index 6994ff4..0000000 --- a/tss-lib/ecdsa/keygen/test_utils.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "math/big" - "math/rand" - "path/filepath" - "runtime" - "sort" - - "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - // To change these parameters, you must first delete the text fixture files in test/_fixtures/ and then run the keygen test alone. - // Then the signing and resharing tests will work with the new n, t configuration using the newly written fixture files. - TestParticipants = test.TestParticipants - TestThreshold = test.TestParticipants / 2 -) -const ( - testFixtureDirFormat = "%s/../../test/_ecdsa_fixtures" - testFixtureFileFormat = "keygen_data_%d.json" -) - -func LoadKeygenTestFixtures(qty int, optionalStart ...int) ([]LocalPartySaveData, tss.SortedPartyIDs, error) { - keys := make([]LocalPartySaveData, 0, qty) - start := 0 - if 0 < len(optionalStart) { - start = optionalStart[0] - } - for i := start; i < qty; i++ { - fixtureFilePath := makeTestFixtureFilePath(i) - bz, err := ioutil.ReadFile(fixtureFilePath) - if err != nil { - return nil, nil, errors.Wrapf(err, - "could not open the test fixture for party %d in the expected location: %s. run keygen tests first.", - i, fixtureFilePath) - } - var key LocalPartySaveData - if err = json.Unmarshal(bz, &key); err != nil { - return nil, nil, errors.Wrapf(err, - "could not unmarshal fixture data for party %d located at: %s", - i, fixtureFilePath) - } - for _, kbxj := range key.BigXj { - kbxj.SetCurve(tss.S256()) - } - key.ECDSAPub.SetCurve(tss.S256()) - keys = append(keys, key) - } - partyIDs := make(tss.UnSortedPartyIDs, len(keys)) - for i, key := range keys { - pMoniker := fmt.Sprintf("%d", i+start+1) - partyIDs[i] = tss.NewPartyID(pMoniker, pMoniker, key.ShareID) - } - sortedPIDs := tss.SortPartyIDs(partyIDs) - return keys, sortedPIDs, nil -} - -func LoadKeygenTestFixturesRandomSet(qty, fixtureCount int) ([]LocalPartySaveData, tss.SortedPartyIDs, error) { - keys := make([]LocalPartySaveData, 0, qty) - plucked := make(map[int]interface{}, qty) - for i := 0; len(plucked) < qty; i = (i + 1) % fixtureCount { - _, have := plucked[i] - if pluck := rand.Float32() < 0.5; !have && pluck { - plucked[i] = new(struct{}) - } - } - for i := range plucked { - fixtureFilePath := makeTestFixtureFilePath(i) - bz, err := ioutil.ReadFile(fixtureFilePath) - if err != nil { - return nil, nil, errors.Wrapf(err, - "could not open the test fixture for party %d in the expected location: %s. run keygen tests first.", - i, fixtureFilePath) - } - var key LocalPartySaveData - if err = json.Unmarshal(bz, &key); err != nil { - return nil, nil, errors.Wrapf(err, - "could not unmarshal fixture data for party %d located at: %s", - i, fixtureFilePath) - } - for _, kbxj := range key.BigXj { - kbxj.SetCurve(tss.S256()) - } - key.ECDSAPub.SetCurve(tss.S256()) - keys = append(keys, key) - } - partyIDs := make(tss.UnSortedPartyIDs, len(keys)) - j := 0 - for i := range plucked { - key := keys[j] - pMoniker := fmt.Sprintf("%d", i+1) - partyIDs[j] = tss.NewPartyID(pMoniker, pMoniker, key.ShareID) - j++ - } - sortedPIDs := tss.SortPartyIDs(partyIDs) - sort.Slice(keys, func(i, j int) bool { return keys[i].ShareID.Cmp(keys[j].ShareID) == -1 }) - return keys, sortedPIDs, nil -} - -func LoadNTildeH1H2FromTestFixture(idx int) (NTildei, h1i, h2i *big.Int, err error) { - fixtures, _, err := LoadKeygenTestFixtures(idx + 1) - if err != nil { - return - } - fixture := fixtures[idx] - NTildei, h1i, h2i = fixture.NTildei, fixture.H1i, fixture.H2i - return -} - -func makeTestFixtureFilePath(partyIndex int) string { - _, callerFileName, _, _ := runtime.Caller(0) - srcDirName := filepath.Dir(callerFileName) - fixtureDirName := fmt.Sprintf(testFixtureDirFormat, srcDirName) - return fmt.Sprintf("%s/"+testFixtureFileFormat, fixtureDirName, partyIndex) -} diff --git a/tss-lib/ecdsa/keygen/testdata/preparams.json b/tss-lib/ecdsa/keygen/testdata/preparams.json new file mode 100644 index 0000000..a5b0d60 --- /dev/null +++ b/tss-lib/ecdsa/keygen/testdata/preparams.json @@ -0,0 +1,1602 @@ +[ + { + "PaillierSK": { + "N": 22032681387392825589254166002071611961795510176942284262351871971549670618699536971604484660009625449182459176985688837869302746403719386848879434108617752884985161357302287740438364961676979177489089466179866012617855055796601906324923031751937392609670591187840063042474702098277371020857056255913020470678685230599191986803793390902341671840356957903056675628206862244359901758797593002246388707723144659171073921898765348966425861897392093552324833706338400794480072790177627266223784839002736561936800034360387906580229699891358571200900940853057926962859942155788202124257165274430766284684864930569189930014573, + "LambdaN": 11016340693696412794627083001035805980897755088471142131175935985774835309349768485802242330004812724591229588492844418934651373201859693424439717054308876442492580678651143870219182480838489588744544733089933006308927527898300953162461515875968696304835295593920031521237351049138685510428528127956510235339193749568093261310343052606512412479615377828002844582063009248067854936775372825140582194003076587162162990463407673428857286985415309333956673562821765396825283243844423720411388044350435964681278482963065456881028627697472020220368389679657461485933972028606789754537116337692072611901356418520468894065214, + "PhiN": 22032681387392825589254166002071611961795510176942284262351871971549670618699536971604484660009625449182459176985688837869302746403719386848879434108617752884985161357302287740438364961676979177489089466179866012617855055796601906324923031751937392609670591187840063042474702098277371020857056255913020470678387499136186522620686105213024824959230755656005689164126018496135709873550745650281164388006153174324325980926815346857714573970830618667913347125643530793650566487688847440822776088700871929362556965926130913762057255394944040440736779359314922971867944057213579509074232675384145223802712837040937788130428, + "P": 160193777603039782130097630110310936197073777625824434344069186597213631050367319754974356367436012914555007933030856536542048874131758319921975132921093399098538143025920151565786449823778219011613726394357179754898922359927920505973696945160056757687537966319161224520985379257188052221917780166940603440839, + "Q": 137537685402424400977188059206535944929128469425162029736774561626978254196480032210249963349555471932192933038919145572169239052429716564489511447773776601730968159462859673835222300478086413562629342039899813063273522136486610254190464548582947233304460132255461390661947219789433008660234313361311538443307 + }, + "NTildei": 21052523374416258971278718213757721007333109676938331781826679720785825418493639110225102609556865245898664595577458711956912561778905914435538549163891653045268958265079818585725154962099784288329465696991665928345368538891907108012452248397293908643310851970981400623991703971449863834784997218392054810513673031286710153031380785503962899023400678278031657780202799764261987122007553645946836830164457173279609274505516962339155803482406843697793508356396614178631700503747205161951578795290559842230841461996525798058311724212961582459459027446153358812306386939882611320658432629920356433652975375858991694379253, + "H1i": 8021901126851232380260025530841983338215656583785707477791518586160111978406304886813122737201669207713841655609400144266320064772762506906975186497400248259505415849210040570694824998148397262229176120689345375520518683499672250580921445881252614823447667553303140630121824130391424983696905546938846203535294903425083780462187973177741492580912044664056836244661418579954715138279030399886036864914070796891602391864607449495986152615154560073587429491492620954208527147166400143730147438503028402746532484900288543218094775794963389875856750252475289000102457276885909956975465502973091475427687111345336576934571, + "H2i": 12509717468473818275037846104630472455989570061807260199915513028356227409954301473687022147943970391271913048366929327844294694288271156518990411476986377667409547483939445173891715371881493230505165015573846555327495688870898374966893451210897431375957888492901935351499322459402811204052356531583229655072299466914467645553953633631820234724378498779663433707849959671776763661241907632351601023537132628995964796501155831272786407601785624988861251513091510065427011677984649863319189829205857245947275000756397372039927014685489258405515612224001544801019156470860823519831755614469814278784237550103823971701378, + "Alpha": 11781509422008916377301666918380954189472899284507566138110026604346489846033924402850380143563036638590359321782559077937795974477415555134370249298589903331453627217139204448438791874419416453538872407689874148024194992982977041526985733543618630555412688459112290811871086659897320426595827770072244350441379689156806385273442507504720539214729042648804024188979348957835399230900532221492989819713715625054463498725141857026390103610654906538719172747479887306307753516041640229493804217832148421244241741013467486611649281637015682014878079144118842425727792852543932343909412551798092227773462891858529863810262, + "Beta": 1047993132013754564665827403809515541745175236824687684667579283063123071514754863020106130449741313439479442399886306266759220090249254477246002516572866951204116514940025488680510991320837917042893644295103139441383632830882335279310390801295589057942347885125160351868389148110477163916776336040826803724114000566114527005029932755608943864097620818559701298132698458825166524930923836127537018189784693920438721778334862454251785150569710595727274566387543977019931097908263693743566261476205201714062484298337534064842890256970530183712844906216365176583577880323789596719027873441225062160610399096294270197692, + "P": 69503856480079061974969061235777736715910386400512085137790250241254776030811991887630602244349166624094568707700874998569751403890792645977074865143415454824167605432711585263235724870341295627821805625836840270963459533015174490881877840436230442430579218236266923919599627675908319384408200636823180717343, + "Q": 75724299487073265062501217779644232762774232586132993399009004516478420423214952922706125132844323015938924411865092395944531657327336849088916962753395436833674206032695591709667142099028989550544679381429722648404827304601747820428075531805518000570414892852649878723214094441681178554836350011201484942309 + }, + { + "PaillierSK": { + "N": 26103961668375654256785835449012770324800583559869394928788454726592065570074278759745436655579230864712234249268354875453548269008571366325566138346048316232943045352736537921098158846708990948770983221523026224437715729443597127270779046599378255410670541528038951636994561836492907022224389781388824430902694464368439842589637903114982809658420483496155304678341145282826329090466751209770539414389457545537417927029309898684942665614699640460921478461279474465834171847421964635799871589589984149116643689871641989161147622007510111490536814188562869551100621664353012625133091881886818295489615484191963214714913, + "LambdaN": 13051980834187827128392917724506385162400291779934697464394227363296032785037139379872718327789615432356117124634177437726774134504285683162783069173024158116471522676368268960549079423354495474385491610761513112218857864721798563635389523299689127705335270764019475818497280918246453511112194890694412215451185323474966527165152749237593375337225525681029523650309968416912062943608549448122905932620836150680746619616391220538361839105573238287877713813903861292983983004453061955682166825952509304954743984231176321011142196185293685783184406624705330089457587585494348224113685824825595402591044143466985977620234, + "PhiN": 26103961668375654256785835449012770324800583559869394928788454726592065570074278759745436655579230864712234249268354875453548269008571366325566138346048316232943045352736537921098158846708990948770983221523026224437715729443597127270779046599378255410670541528038951636994561836492907022224389781388824430902370646949933054330305498475186750674451051362059047300619936833824125887217098896245811865241672301361493239232782441076723678211146476575755427627807722585967966008906123911364333651905018609909487968462352642022284392370587371566368813249410660178915175170988696448227371649651190805182088286933971955240468, + "P": 172419107139509555519718541012746372547644336670724082735233001026323850117774310110504081076266549451791178011094366062898654058315049908309071763092473124750464310522900924145315227546322784776719859971112851924698348617175278544005585130510012365947830838164462486430016607473161552448736837471569432252619, + "Q": 151398311367278703812686098783312611421787797425533294985975447975879353131878003414223468071518694724133509785433091545320333345238113976856979070379278755115741527992939800290222710138642754430435861438176495214164881019747461380162415808642197006237615655199853690475703624762465937858790359786421827221827 + }, + "NTildei": 20962551754751728223832615998674353487159412133629744373141121294976078617468389133432094615714371093459379928798207881724809204474897920582366637643940514510901544181208969319089878766965636278711400086591282529548335895775691829139799763858556042152149253868470797894402514269625885059535883814579895539572663674626628108602754585629543129531843763556953320310359571522884862716925088677496098844124667140184110112543267097223965921005761370635006424228732589020365762753093226895145242828470061890267793327923114476291890961096185060711765234433336622875030165329580164494842021314940993235202719640032782235794577, + "H1i": 17891687529017852421161986796152942266664178361950367848423654738245289549267834562947653891652997277190978507489809773147203716610243039514972694499784877740697653944332182702270781627738851291995930859750413478173245364703084115710741806513381310226781133473729375606489966173247420876257392752628290578283716873104244273767109415193660209371520607256603269572574788296836008300100105019977589836104356461335068232424640896867676041905056842065466989250063253196016710662257201762401289441771841924388026608032285179009761523983611215771408833027452661477531595845325493860092579331780068201933907011996776700204056, + "H2i": 7105557895470594118776879847246109810092156164266731522628315775968009110525433119655845287839318691162225575746812148658864832201304451229203154643205932999528634564963360275860664202404305147267146917239310024441847345640691114861779866262798511131497496552230770228369902297812491551311172069512533218265456720446703770032344167630760305501687734891316381563760078704494199451350905500934511340084401742759434396756365456357480962913662966556828865132676499090140185620160619901956023968102761548268797290288747768974491377318246608216749915808906725014024054547741664661223065126208283713091832766584009897851912, + "Alpha": 14252867114905443460266463891400976051966013168800524308619102428474397355481845473744406470664497277675962237379943066626373904834067351285662036202898185412082941312333862898451730364274768617037638598720690737258419996069842596827107171072804097227317762329726211232114889256143809834239192740910258430651277614379530952612901828075439027708875011231749240069163905750213331244417333305810335269206208185793231625999383730162802111149609088588272728381960988826168493227752355406453217395346202893126994852771381927065099551988279074382486890211944156066290958803704899236205136289485062625239733913120833491438619, + "Beta": 3308477601536449538686166252362646519422957799272510470045492087015704311807812493278640139187248735483806843131297885228643962175295892486465619687490938353036408077176590199877976090008307150939043347379678036101109052327523501557634216520924962259710188384339883645061824969396528097483804441367396204838242771047166493455177136724199301563861057966883779454552675707159238120706111102386124375541184282083279983552088370568807805676770285029262285236302230449430314856463275281156205673493227560462956570923884706215109200568587289211194318919691691075823855586679724727157196631371469618780186293983495059736343, + "P": 70058960799688057566638526044289506919512841006990883704818823739058950488771071829118710561836549353483249532452003782056045357972705141393632336058865491578432683572072392504299199119762747571996889494742264646996448262664704698085763505807588148363607487762245835841547130020014878898623974346800466877579, + "Q": 74803249703801863468321726931457189115947920748302204757078465017335878850255515868102917776180277057317207211099024163749781927285857741070864963322967553574541575740407431582538206772941200146797750917842591768148280498505488211533808969270143445933318751356309388889526126153915398169889021689673467877451 + }, + { + "PaillierSK": { + "N": 23325205227925269234966831900835479518092306244833499095261694235596244231323872359308411977519955992591209944049942853108161557930862103374786044665075872815753771225523951724437713919174168132257652949822169429515394908975335444320395620730848200991695783093123463564262980903896490223036659773976952573394729960836306076073488806770990715694767975908880837452504749052379568621394898065875783943237224678952355613305484983905867761392281013454017034625608294097271017440060719729441016257233879881980789738436305748104466410983385589110989500537636737526939724889748108479509960189543769107525416068207577281095001, + "LambdaN": 11662602613962634617483415950417739759046153122416749547630847117798122115661936179654205988759977996295604972024971426554080778965431051687393022332537936407876885612761975862218856959587084066128826474911084714757697454487667722160197810365424100495847891546561731782131490451948245111518329886988476286697211712880632111761535343366539385588866331097819836681771447494608447751994328436555841843596624346445080227209576723998224222675375975253164395390398736410938918652865114821652738543486923855299177581673032682318678455801556036978280595322890239724336564170214067662563010358176242514130409844303826771418202, + "PhiN": 23325205227925269234966831900835479518092306244833499095261694235596244231323872359308411977519955992591209944049942853108161557930862103374786044665075872815753771225523951724437713919174168132257652949822169429515394908975335444320395620730848200991695783093123463564262980903896490223036659773976952573394423425761264223523070686733078771177732662195639673363542894989216895503988656873111683687193248692890160454419153447996448445350751950506328790780797472821877837305730229643305477086973847710598355163346065364637356911603112073956561190645780479448673128340428135325126020716352485028260819688607653542836404, + "P": 140393811183797838480821906981452589420195411605633028540770946408190278531775108359323627215540508843226886590449120098918917445439766412940054444941947533374733870455349519451843339338884553944008926035822510522426677956287326530248527234150950297839523861854685125196139189091902708825402976840244236198719, + "Q": 166141263858054711937298130930491927615118301635531060421083116754482838874466084404776628828435477218968272295882415810500398596089296534748189399868873742018446263875140566683695830921147617438425649054417872944682821423986188624179782657705307780427072687465288029187800284099381370439193402759679502059879 + }, + "NTildei": 24063125973170446041881848860624212199403222891269978377833700020797999159051608843224512736934618633222527679607502628112400120150711545859322771057937134955171933207814985594883491372433104898543398193213899332781156243190668067243686370991018586287806948152272231283689037372100075783891486765705146152958043103596575551428577898057190586543500283311190429180129106035783651392594198726324830749514861045473143471128976159097904539324000528163153243809415908369537333105414799787920817301498891289856797224635264435540899479902709869632703726622701833982566124943366465226336103255383089119350335203106822915212781, + "H1i": 4252667289544615396295234358681340129559005698047823563379073045036163938655902860749049217982380377365223510166456638954386973542787766939700921406447677890993681530076950179183079589309150839662953548469596508482901094520996167457496451009454252423093053520716470361751316025345288967580599957461030917817152909204038507869302396913186243074540871775001099613937181469732120556451198315818783539076115603520126888406202132158095900348622127267327298962556485343299134596430070339915384637185428849583176169343199373403036714299309357839990291176606608216226926277870223276401427032852047006558172680729229513177117, + "H2i": 1769523042178449999195644558894903069126428428084272255251942147339573090182054514450431408133144177158367244251203972310078575625459268005475013633456379458105920858500058709453232758538280721954079465954457627505470785905947879157770549078329594719704981105146079898451796528801552339542684188613565638748213055827431749014582883377409063429593840491901349398017447549473837915085947537144739382934769495498491993335727916394058586319812028051512055086836516351861835523722109852903246757437463194658040354526690473587931736766050417825790847665614359205294258644505542435237620366532264766041606438821620951967663, + "Alpha": 21111964989079510139986592923694765231789226375036434129654330227578162066579617104686617462346607253393668951629598894365476419326938691992033775402545144522177982018039196366371398087338564197277078110023243747936580822271167070344519764102671860370588617429792244651260223540786928714632935650156899525255665897639695627666001190244601940150268534984454794487750584705290458366850850570454807688929895016647268357746175655329792242070136303154643458130678283838555340035684167028343178150972950950358623806835817746381459834788085817808072578134932259768257195064820693426664906997937436179610417969973178015600128, + "Beta": 2286102170866173920033531133455745277469341691660865279291739273898211446827236040594745771849333978517591580773342729850666235159855606241523601131246870067326298810695028919639322503482184076319876281111128712445178160946968658343137564318625153578028826448172079866408772511262472474830430345842724390506192941644127287634145291021791940292500886319166869989582515855132962718923754281751348369256225237205668510887802740820278895233917695459358695976393176439038359038656037126380515277536333458692936817507926171943678200016184905366437480561577283575228529697297234085593033704593882508939096485126814158427825, + "P": 79114110889902046575604303871012753682326787862748141890597996315769943446722765787583228134894029563444114129300035560585563846855362683552756112373717297135950622783054480691603425705634636931500470593427005599027020423835674708543611706731824725434892055537618336440791740654956633376367333037932480182973, + "Q": 76039298497133876089837239761864508901571494421106969033806513753093239509449368966736828738454800670259915363368456883463231588697171482576434754063389097591306263479246257897982507159326372850917042172117141315986415412244756510258301246592233895915374893669381045066954614949408758366382011430563049634011 + }, + { + "PaillierSK": { + "N": 24226511361144744094110894899604763482591842957796104016638816164865158900625300778167373362100531443821235120080053306943906236666524449187729888783138788711875737904860285122266912375431418748606924270359794150789457586652503737031542147095967298293317976041243066245794409801176460609198578381613091841939222415197262381903503170096594831139404771868828212572141056009219553628308209843539502929267476702668157458816638204847428665649782252333362303250926410134507918088259320009037262693059595984867158702173915692138767179801985693428541122053696087590919256521962154459229408262162570931853101339791228970484581, + "LambdaN": 12113255680572372047055447449802381741295921478898052008319408082432579450312650389083686681050265721910617560040026653471953118333262224593864944391569394355937868952430142561133456187715709374303462135179897075394728793326251868515771073547983649146658988020621533122897204900588230304599289190806545920969455174212873058751563367880620586412452252807853322389244309428964327933003536753229998099887234564346065674698335398696012799943929444899816035105573037845377206175257530039147546723853802021722284166591547597482691413109478467302867808171838648654741992051027809451558650173605284414545187608330777321710726, + "PhiN": 24226511361144744094110894899604763482591842957796104016638816164865158900625300778167373362100531443821235120080053306943906236666524449187729888783138788711875737904860285122266912375431418748606924270359794150789457586652503737031542147095967298293317976041243066245794409801176460609198578381613091841938910348425746117503126735761241172824904505615706644778488618857928655866007073506459996199774469128692131349396670797392025599887858889799632070211146075690754412350515060078295093447707604043444568333183095194965382826218956934605735616343677297309483984102055618903117300347210568829090375216661554643421452, + "P": 166983550597135694677295042364120538194351068022193864614902859559729199240332299305480083766845256707531539489607636494638151104683845212132861831960863133729769719848383654551358754812454616138210425249710339047442913301472681293678720053837218796688846506405097891210756024809692986990170935142068146852303, + "Q": 145083220919128705699139292989537776305915185099373929037534291731168563060804037774026645726162317268494569930359770960764914657239517321597371207819471310023736017895876276190810490539537325284379943741110158125941440281556077529126785656181571484746425913501437664901351890142309115772555187987606180210827 + }, + "NTildei": 27339286075147215643040809951987723175163161243008913019979948081440585676858405873493540624998073453984661239078374030794487907388443665149050246122096760296507175896500292691497776336258229695229951054819526521173467785237599580756587421391481124065022772588139569945998577816383173900620687006684846284976926564921683136889056388384077458570308312106992591106660711942688821008817670027778670692365091235462900209635415765784855983918908163114366056759683577008897085980723740882412258734358997280156671124288447785361641159599057006698558146654911087066543834860299783526648121237873270455617906451482814775292033, + "H1i": 3461013326772463112617306001903730979189654296415922609288334284665462228898075547230412123200445927043096120083845416729937171658647712744087911369884014340207525452537835293902924818558756084454755860017415323439403456814384568821062047640367696084316762791005536149939211654734082178675355461625201699075499235520382853887949943170441620761258549869390475914468851340411118311737864428704518672475625416122257196588934902812279539840077408455883935055022665403342098139991085364510145217415796572546898829930860363253718161166118974031312746229987175817290762178424229557619133264604216382598254175458280089002635, + "H2i": 8322126016246789583982873082848006376261470487894867719706259748369213614435115471185039876936048527363454562623166093733893457294883939824802412221922408873971609513701107583907207386818180203918474972745521470210059679125868556875914234722694356168565686310097753362775535461421486379582176841493208859172945730320643515629774489539840425814435950640747280796438490990823026960006707118923268187128851625045298256979702832963711034584783603491543860082284186511560998558369036629673232130820281272262917481201339102008547572688851505544966670756938593054706754429034877938281771981111504973287640780356734874781455, + "Alpha": 14413995018156907647711998489344289985298531961129879503474835642367814456597715671073969991877626677416537006931808110698418694181095500271438342781252417377518969210083888088915208313503970772950468596812780310368544913589562619593146576381302908453935359218230578263371911480573916995601615884869458261594377894567036342430642134653814989048323215003033146653283530620877903805635445830080794500803374298366094458011072024720772676049976468530568562660433222425396465849755174221617198549569629702729765837550030945047096713111289611869665431921811632070116122763925782204805411287525723093777728313975236218358918, + "Beta": 1330500725969461471421840390984442124157542903012996157331511181870198607187050218243317463482019716881496675565018168275103630339161208257899421023813897322580081910092343091667510408817032978584878943283504493499140231495200277296112803229477223503329266339280505029395566330134033435716007659411594218791366530470041606157689345932997637244568352538584533510431320525060329037260326125247916053113396876638237685481679553426350088825710694097754242433465223532648031008655627862057348593139250460162864591552212650411083026607267555086033731448578614268409080730471897575693179091660336921216828328980854321318873, + "P": 88956867866820603258576921374104964002364820318744886578631656530978611541901875424525997693257890457437842849196774467465085681270613788362897457687412769970356450550185400803825337329739988372745551032604468593802197531973775191007584935593137630129541330880714555197474212163677069137887516645213401885983, + "Q": 76832983025204689534493982309794851303769495257598993307864963831890659852654197388288114470603833988775139906179109969207383215985533224346196774958340212096132713646083940895183176187204420256299482631384908118447711192486195166754664047570238320608084428304675796337948687959175934628918694986977652195999 + }, + { + "PaillierSK": { + "N": 27105461894349183309000812385368493637426733505264052480072119319546512303618874411378402805169727463164806936750986572528386200156936676894890080365445014999196958191169375196635860212062931831170892558037313247465057244755272101122558552019317433228619357821666366467985158094501036413997695521607117793677858623016773096796815383764979733633392436252143362156513254589387546633261564820084426126742222583720853005859696533126654639975200636273256007286633158310777388538957502635387387355124020592283261350408995077766779351168155117861243450733106720613131524819294664079328842514935299345835018731284903782234421, + "LambdaN": 13552730947174591654500406192684246818713366752632026240036059659773256151809437205689201402584863731582403468375493286264193100078468338447445040182722507499598479095584687598317930106031465915585446279018656623732528622377636050561279276009658716614309678910833183233992579047250518206998847760803558896838764566408586139010696666908146601515183652550551591345838860405107979219314198373534626227948860633900645313690052145340761161511409647338435828523705825762172799003234259439469260332849759618710557536169330148636314935446085524106675311520493656291947832169762791650273754928276398713795425659269191211351446, + "PhiN": 27105461894349183309000812385368493637426733505264052480072119319546512303618874411378402805169727463164806936750986572528386200156936676894890080365445014999196958191169375196635860212062931831170892558037313247465057244755272101122558552019317433228619357821666366467985158094501036413997695521607117793677529132817172278021393333816293203030367305101103182691677720810215958438628396747069252455897721267801290627380104290681522323022819294676871657047411651524345598006468518878938520665699519237421115072338660297272629870892171048213350623040987312583895664339525583300547509856552797427590851318538382422702892, + "P": 158788085959761880064950589553428809304097689194484592403394790846272833648628530830519634638771714082418120334894159706359230745142508768234452429219922099906397173786804331828077274545079808950139032892207902730659152846058182223632382910790077954115349316484092040041827074889581946516262790567489956705967, + "Q": 170702113641056895357099359133101793721033461845694872432138988325315360984539542184654036205729601837144258144698082738773086207238832828149897810001584686525393358702179424620789414879421545912007245178126877763490327429925887424260444781329330075120511163284988738739505583492919971727904622179031402825563 + }, + "NTildei": 23691436017855427690744551925680675751250741626421676202507912240685070886624505127975370962794424815402470982063731900673714286217600943997284523150588911399323557404444317717883078340523175037661371183111219631362366992229006006220783399355107104502226910182244158617543778049362407711940835675954357455142511938226501821950216437105254310159134161714439222013148809846710260323775693624459468062552210121052382247678518172694187328978075519468879973412728895399675080384664498095055842545978391442980374038712653280030532582875548156807629170435793732243596385520898213432366953221704775007818824521585883959203841, + "H1i": 17932193002987671574495441469409127392370151543929270710351635414221934734562809125624243906810943108503967405005828654232185330119701540260824878342500666498535306144136372526015342340296503335394172410131336900776171942656160842033785839742979772089804272322672695007020119040909512697788132115871307948965619772340555262326363558343641873163576164000204585700653067269886421147844891627786467545439613998367235754360745740779037900502062630533212555287083690898112744174643195724344848814257174038939713079456786818479580505563351639235638713029134516367564483951764900764048341146360703413290969640134091967290275, + "H2i": 22144511485181764076378632925055859554517034281914321537325450754791188531438898011733841223669386035295388616172347057818335638121559385360966413699065274132284819173472900569012429525374927738572545597101140946802265126843018662290567556996779559867704199901918249942568050111783255047381864793539862698215895443308451471018069037594826987413875138189941491952651763391969551652771274778053252888595339377841941751657170177826288275027425903120808102958067955157688362334580580616687045142103438735764607262106361548086981307576645889657909348999019207526484743264234007721605934608721857264017021201801228714073322, + "Alpha": 12475454871977640533793742001964509717030234369319054761283713096754488025759647264617618667471948169707595268964990569463598044205122390140472875183890685489014112370431556067320597664541969687785175940710114453712767214199171556171508500097985262271060053417665005465398879134264915521128766972590273506751956916658661495945567005646459815432560436844474951445661121138145961292832389878405254525744601890459426832794315879881710578610428146356911396453602498624346343946747856118322185468467706906642669443812238287626221679090803160411080703449986762292725838665480654184225731249142079901455593074852687003407121, + "Beta": 3347757673070848815750707814663538545831756955658217870201384478065575926254131397933932861321310014073876162883389033326792388023527881801618972406965570525406692560066937269527681500420902800339132659175307730861124433627016852213207311176944933546395986224251842303851284221677748437572008633275917860849146067320000067525147526929224843434676175296387001628612065916091898157803746507708977354464618444896580512294214469637239942495514997184825033934397898996042157656544219602859177335011399755115685998458424801262820483385480035147963499880253328287061760124677500512068646187505012636612192709673877113813776, + "P": 82523448872461885545342850364161285845198510758875532944054217810743763485150649436008920479472261720115273081343702596921073662853817491862139806529369649415859578315023674101391853182691852213138751532233140788368741920415669029119339274824835905811640381098821585768098859128301231076229752922643669756753, + "Q": 71771830738890965234415906767871272848484115061921410007753542465283517419097330028056337315167049112766374105979466657537800615396370280646178720246754836375136008560838529382069672777436860683429661803464272685067373809575464139727489809395705517046029291986631836806318070281387838773315000750346147957381 + }, + { + "PaillierSK": { + "N": 24210579506590879595415817848827594816501513507200083164689498948679986232303302646732600288656128886523560558773695824094527846112596017863955871733258029963186528485033611772941473960967926900728268924074152719281076374005063841643807751604681895330398696426165543442661663240736536326142637610665723927976773223804704133617358537502650826107573511813956294659639755207395820555630431703848474826839841653173493253693385559890333059832962249252488665194632904458168785548708233660058288020527585772053436305336267609027126311040477485119240509622073303953527902918866190679485955288565964845676245553763836894383957, + "LambdaN": 12105289753295439797707908924413797408250756753600041582344749474339993116151651323366300144328064443261780279386847912047263923056298008931977935866629014981593264242516805886470736980483963450364134462037076359640538187002531920821903875802340947665199348213082771721330831620368268163071318805332861963988229676722905976830190080433905272301919869241900186224400838023703593016549060081520844813399605374355537959724918817750857465190998572126418846754334344730979244444006673618857816570858514321484077497938564152559439169531545338833054799625616507437091391254134942137438289358574296712630712452614972137363638, + "PhiN": 24210579506590879595415817848827594816501513507200083164689498948679986232303302646732600288656128886523560558773695824094527846112596017863955871733258029963186528485033611772941473960967926900728268924074152719281076374005063841643807751604681895330398696426165543442661663240736536326142637610665723927976459353445811953660380160867810544603839738483800372448801676047407186033098120163041689626799210748711075919449837635501714930381997144252837693508668689461958488888013347237715633141717028642968154995877128305118878339063090677666109599251233014874182782508269884274876578717148593425261424905229944274727276, + "P": 177381965041522402160061665459054923100428177320810181945981375184402784271101698406233454313887906522836987486034406428345587150387649619078234925994813088518730838415835760634314798880865706359307205178775870401344284610385737551430222207243332359340768362299438682542454230867680980712149117049852277388859, + "Q": 136488393850657554818314969381226580633345152835112028892097784804231738261209842400551745726742997939580346757513517960272542300577455380572736759969401907691565822279050661708340079929691422725974104280363433506903687367001069901700688163596956720004352048296867722066922340549690439702671531484040342267823 + }, + "NTildei": 21825923055692363363807856814041788297932352082686522049762479609248131031493209178616315332678260688081237002473280502673900897153728674074250978920145603272890375554421010544375045978230115152148635406266868721849462035935066549485007148826731070427853967064565478034197086793128579348456191501574069197527336381271239431882182590125002370090425492196615622157373084894744370877981651753517739740180746953455122867818868889767667533954285848650265342352648994696666663166969311372855889865099834423327240443645946623500446653775668772232699108591681632208777141414261094814249472706286495282111497969140396482021361, + "H1i": 15684164076107486362647627086189839256071730816921159825587044649382702813353249858805918238913067574430611789985157531061885721123720221782927684432970928907539621363773449598241979707937789782663129224896054270014808240880961575531671500976415854986289417648719437211694365683294130280283560214173079398846590084579457505651739766782465078556211119540434074200068804614435241712280915634650903672686377877661033196824732485185050823525529129460360514976505602179125362017513656878633359575448869782973794459491323649244386533565088224614927219166490439963649314544551807575603747528826184191141107064431052311814111, + "H2i": 10937957341620608445027357120052929078414141949388811150248709043071998593032641885646815075674116382573176215477259278749403836199301249125992984196478438343573106510323359252348218406174641887390259296850122243033119962428309996387988726358998038956917625170381238080857980422489012499771805748574379337089815869140942326088225688169969240362341247885407274359457824667272277477820414925510879658646557925827744040438666460540701953969793123734196698457916742617898500655685277219715696012129696592052086528807524033129077162474417417876027343037811607066274564941807607132572606056869032244031664105944082462260040, + "Alpha": 7382441603778981789049097286373899782763514892108731066297172807764403988882209235804328196924961245758712156211586446173584232172348758441051517953970932017638801228579942905743888258770393992428069958582875754824949103973366006926096895034187574862293030891755924520891887599837303736784661079762915753107874045297232748861192090206230779111716801320484889817963969027040956364851122145910342837585698833070404225184905222895161394340456991918300671707332063504510276064035857308120399388827534382418618440504293632241252707321855824914761827312225109282211684898606819593839303057121500778743615359397457034092913, + "Beta": 708436051141781127878868574422688577554367194479729534264419571972132658534477208665290561443956154465618358950511358859434190476669625127041269758144450847707027420019028639224829761202087088484160374252672258067082338470665694336787011995891137048270730792257395310734540990073420042289150127555543196566554711366496575588711628921909577889068884910521718203148179028215188204631432782654373974910760481598092652028192675763936883220551492979305102099548768484938113748450314318866586754316995207932168501725692912507398907813438681582391117157798875916409585766188767602969971902826424279053520482798830944265880, + "P": 73905698535655586230349346093201129201557167554780256808221506486306575694672676365166917557278592197808755100252284140420978046774991776975293443640409563621385798103596241000569285453894749792866306533028412764860475088073668106682198739416911275855020540110986230668538580392164176039576002085621864023099, + "Q": 73830311762639355793188275321701655294621835018962284029789713083270057112087920473550055750699498154159713687587041798639840638795396409553202501378985986665932611200697368494143020850410182216600084587454433425689098255729763320578480411408541235337848628812709372129035207686743609227178425072166271130219 + }, + { + "PaillierSK": { + "N": 24322215303367550905210110765174060759809472178609848011900853683380085516442186455124271929266342825348559686043500955269265930297750350188223279978554715682735202276928354304246204851496680784667013660203145613698997290355302794883388191194275396900942884186325451133403043288428790632928612676529268980348146310180898663977342668075672748773256254787902933156297712230034266021174686185315276225674528280984796363768987990751830394258812264069408824673612104894624676015022466455561072031894010442790059982741264561513834032302374674652486521382708574019730969187102828218483187779489423227024825074885166607940177, + "LambdaN": 12161107651683775452605055382587030379904736089304924005950426841690042758221093227562135964633171412674279843021750477634632965148875175094111639989277357841367601138464177152123102425748340392333506830101572806849498645177651397441694095597137698450471442093162725566701521644214395316464306338264634490173915869692136837075738294076856810260292632197426285178013579202293272894294360440306544298444750341896969593373105936387103451084798934421995104901165470748595521592117809788279932397439473163397005408786083322133772539290269046960066503169281554215906500582776045218742347985521544380157442156627269565545138, + "PhiN": 24322215303367550905210110765174060759809472178609848011900853683380085516442186455124271929266342825348559686043500955269265930297750350188223279978554715682735202276928354304246204851496680784667013660203145613698997290355302794883388191194275396900942884186325451133403043288428790632928612676529268980347831739384273674151476588153713620520585264394852570356027158404586545788588720880613088596889500683793939186746211872774206902169597868843990209802330941497191043184235619576559864794878946326794010817572166644267545078580538093920133006338563108431813001165552090437484695971043088760314884313254539131090276, + "P": 136877526817588181730962035264559857243502564114609352610401455595289979390777578944484265568859428722136778378611035804609100218759361481869086079762491297117057525162593904102460467651821449388783994365542445810242683186600354206877457303276844996569731945051239640374264566775104838809665049725202563694119, + "Q": 177693269807401644135117886694568395427487828935753447660152369852430253195187725757703363216168168468720398644165082173014391870455033743549528791518672100316575305624252974898746769363242666607265170803555471436046270535236226525476057740868620591348236076499498140624227241671229627900275711905424913155783 + }, + "NTildei": 27497108900777725727943201625139008849102931022530537483093014533131531722651541399684618860000157145587008904377638733268773348021664121792851954996533085273085495560279031694720711084207998428476676522230268713348371573024058605159755832823734306460617375660576683401782139459872359159178345981307664968203927546979252315844487326577325467173205249032327729213085123724468449732074491270897213998196562151498338923589825574370637803940435864178801463898840165952581858265362652296033880682706345688479821392899092230186653687701003674684667123105747158198612021687738087468561484930396372459125787723101873736456981, + "H1i": 21346729471241227353829325240029509476402550080017210933909197858833364879613431301292805330654979203140234733083720939054865596901217566576992209746790722941750671985357643908114293587068186876212092767141995337558381088546762770427026688341194823384748480151633125365521603849082227158287858242841513980434241777312228446476280998030933540237084294011016142841706382912572790857702759776494964228451362332325760993364320615057957059793429176241225683506615982542898486322656113904522241790564667788547860353350406711138697809187335779562476662654995219586733826169659545503981626770715163378482774885953498883957691, + "H2i": 12771862802066948874963858131483480937294668868300800135102905315484546586075858318364123148739557722495535186135418735753341303582091734305231344298425670555530384055380408236043996167596444797576589439877144874859862141455176956503252202710701994934023394972205689090738225431182150237620689665508112428149309906821872259207478340085425082172342241813241167104154346505803226938478250581790279871536139999834295400736265401318045386518147347440182519187979059701331607320416802936607930843217203167316922652725011502954309035922042107940404209556488808884356651391255615441835596279032845362289013867575406501827685, + "Alpha": 1222657933149133737786041212173211386741038246314956260446673928726028348671736646953311399385644289270171674551976597704642978669509879984539170782174945060979155772075239872274861137841746745183931109538608650688835352168473229387890908313345681954747076497873114893004631507516909862632335732748874704996432343009427040226788085549213712390108892922264937314220438530330367683149445790928829759615854794533852996554825296665739416218080587678439405736360016866117357999498631948148509919603380984304242817553333964104339748444165511972781118673272557520616543604467903273592237258785476061414081176127083609334691, + "Beta": 2646462814138752750020121583793941474170228657867677366535470651616944806249189517400474444856544343404232671885702295263985413717101959766957790638385238514685784380850232373820367283100320078197266850997300405722279929663278901685149424660354919243625104524015520276272707859876015642870614349095645528734153442524657081382069817549676738869702746887804943929734535670250833123979322390475321261975804364428759035738848874226140439498241427804870111793101984721448971470970395334958710763045310189498969304828652011076163730486568854058302983884785075204847110249402268710501353242834866566717225514661649507000758, + "P": 77593370979455168395557239848435040816220037251256903737538362355163564570184066753549744543127019354447391190078401474830848248339594411860428788762903037388068490569528957274370767081602598161509743315026951897441668428554966489095452490387554101386615467337396261984449718212274997186461219511649789904233, + "Q": 88593614872262378325659889964549995339937221719408679957332431421692600126515700349569605613433261770900044226781047267829173573731523231925716537287356604239803047282305690539563611237400245842950779085918924194353729295303287397383289930362572642076761100978248822402138288188721462208058698633544163549371 + }, + { + "PaillierSK": { + "N": 26405387206910894117205086294354246640976260482892374862320711391831557024085488298362593032510502479654047456662880765264859125860149425444559417662542287050663571682126431640513473238646820791279640739202987401352457478833885390436121679020359543926130790525072188820324703113537629026410032890365515513677900245329062309272555246825763917111195592052209023783548831694431105478645557427816564166441715897573751581621513099354037849551939416133205893554124030153570413444676371646855434083564732955755455974741393227741248659863435338233056640853169482895367991487028793858447470082933350955390075499879793315531337, + "LambdaN": 13202693603455447058602543147177123320488130241446187431160355695915778512042744149181296516255251239827023728331440382632429562930074712722279708831271143525331785841063215820256736619323410395639820369601493700676228739416942695218060839510179771963065395262536094410162351556768814513205016445182757756838787231762630180414289834905358212887386732498327159103281358454806839652756928603602366067381846350827801582660473408447135693708863061080896988514611819573759047143445069191933162706318470142965731561174297400421967766511408664101636900244320803506957599675546419767895237105310780068394580491841375079944778, + "PhiN": 26405387206910894117205086294354246640976260482892374862320711391831557024085488298362593032510502479654047456662880765264859125860149425444559417662542287050663571682126431640513473238646820791279640739202987401352457478833885390436121679020359543926130790525072188820324703113537629026410032890365515513677574463525260360828579669810716425774773464996654318206562716909613679305513857207204732134763692701655603165320946816894271387417726122161793977029223639147518094286890138383866325412636940285931463122348594800843935533022817328203273800488641607013915199351092839535790474210621560136789160983682750159889556, + "P": 151574598829656571506309834766192962704416055103298598243509746282585492326683529064741306452907061921919393449255966971549704883979793554126255828983084687384911658312184413018878364181726393990420382385862049293754923305635942256215666701531373175321518798342933078582360870070506864019271816114060039893503, + "Q": 174207204972291872469267180281298373717711000451406978742605038534840680805016691547090725225116133996229022851310315488216757250233500417285660695917306318667407499474048849970230306746066275833572470006936377603558203534982067773567173662996502706131273337593021244074635002241283954581642700082983115748279 + }, + "NTildei": 20313358558889897820426530401634602876114284534284053122141742845485266504290495921388303644815355815840285094208343611225617217498355976100618719490273296554412403101105676169925608992228311149528165618892830290880853849754817647042112766663544137102581786525380078174767390186202593552247142160925524241616450810776408078057489854536493710576933458614239060695424904361567472240321945899295472212916382244989406650943311772566640490685190613590084387813921814214848168130025228068305538866804240120971290359944530794356410458473864004968706726209335629590404266409745892726461519824037009473995213538176916459652437, + "H1i": 19976302334672726376066495285754719570620788166921910544818957920227256819076374689278241963451430217338124191882358103002871647763201505354597680111011306635139418451938783836583979570103908295759137034100884312416135243009276524839814736647686843871432553999135898638782478681335395765387380411541130423150446761341993669599765840047682725560299913209344663307856115518537613887473966136039478547655800206219994750579788006830927973451600503281088613019927577259451349644910748447941121592693725852555427688127331543617386638344229186651119266666080999968600901224711990439406228806399678704297048981044635144473475, + "H2i": 18631405280291603937172443146695452440749769146759778074335166651065821884484819708951819300228977419365623981832401378804876174585505214320800398630630531146206615938924788918784931309698479344598192616825219817572674351668005842694350127549903303670459667115528741681742140008697786885393009261004709651694589344002651700504353857667120687847233240208984142775131235334873789995578815007148884005078809098382179933251834318083903999521556633688887866566026414033945400876552289057714657358560959728384089304049836627433179548597930026091575276705808743856974141099944502815867108410421424678647325201978292571161363, + "Alpha": 2730661158632756560611314052956645711420878372401360554406469893275441022534446460465422612111283028110115050500887669569269944021449207527959554411411254199479134724168696956819140143910947259601860678666029320064405592306904046147583116663433572589083053985914655855406633545542443586399388360692546427457001155384320713066314056302840316096200269069581379479974875855807236163417802525418682027505301303791573782921228592044857666146948234229705569965343888819412539557807228415390687595116628897908415580352027089743924613385775139343812646145829596792769026407063582455040755892638534276435997367191728939876460, + "Beta": 2062175012385805537442127411524423711617301523961026175569207074738938672588791865220816125321289973526136228328596769123634519206128240284364541605046232630842631304310645656494919559409548548522840259121826779938111620803297245311503922710337190471093489286688621834742331600613512015062725917383607614872747292588904733306058652323975937460012224633093813157052155943473964952907006910962219394076584582068874483912450765598802951724538911398734624720155606445045215576888150119305806413059705123844834343691203215265146252634695828999581057604775488707390713741576587496920955633103007202130050617474249091089894, + "P": 70909461908101590607059282930954972121095273800480069776191615829444922668400326389669112012690299620000264181613196692272898022301452164027898548232014369759656337665489671742199008301053605189093495157555337910509002506605118072792382819709640028161171191936659294606554687876789990798123958659751165959729, + "Q": 71617235599728347845047202736174520918450078071146602467302052026303133039157904798881718813854709925699814557792601177985527578479711915253460292064507284749952701335248164772549806706414334707199970565454797983289486793476446127509893581482577287333670725324876617935642029941468101713149702142803183021171 + }, + { + "PaillierSK": { + "N": 22587155936009461495683845337009644427985455251655873901399124810358451827820120570495002462756945466937228417119258643199984329619581338037827366424504626413973345269633865749350596900936492815913675733864102018565297945571927086535682396949692273791254572579126732118672518751661509857425298524229756115683514524246192888498753806428412631823063859212898488618466052543126660100961366900844204698734540116918141657632672870671928767451329597683095873984777722119683128704294128809953302349136317872570175339662685889548027561948264235939854374573029872654479603112283353478191048181800886353910844577664011224136077, + "LambdaN": 11293577968004730747841922668504822213992727625827936950699562405179225913910060285247501231378472733468614208559629321599992164809790669018913683212252313206986672634816932874675298450468246407956837866932051009282648972785963543267841198474846136895627286289563366059336259375830754928712649262114878057841606728708789840328877751817529048103105162778614946033508658679387013483680394224078892505503212142791456312857489678891868902096524941744052321894423763455564066198200584577639198770513172288524134359942977215364283183196965377091764600867337240053101603231811645009681656489542357739325170580611903626959598, + "PhiN": 22587155936009461495683845337009644427985455251655873901399124810358451827820120570495002462756945466937228417119258643199984329619581338037827366424504626413973345269633865749350596900936492815913675733864102018565297945571927086535682396949692273791254572579126732118672518751661509857425298524229756115683213457417579680657755503635058096206210325557229892067017317358774026967360788448157785011006424285582912625714979357783737804193049883488104643788847526911128132396401169155278397541026344577048268719885954430728566366393930754183529201734674480106203206463623290019363312979084715478650341161223807253919196, + "P": 141980468218021086729425270780989901628140983273843836197486412143086997665367417864947552967985064821254794961887823159884174866453944237520060398480071561024921603131139952545565508692859561717917207832737687954794504544145392174210819197123247752455249656881072756041380574615157389645625228714923098947043, + "Q": 159086360395186754268877522573545715225392672394752715251248772209546135935211034821472134760130766513974236955805689728306788391825769957471169797450123647530074704761819702129339299417113733803989411943993770864666691010188089582114353641232144795821146991778990702786354628101013485614878187725280871269839 + }, + "NTildei": 23002424993362949193922489560733649549293742111450016061470253657213366532315656988922193595049908631689658293221982596480539653128660476721863567039916060674578671086715450578260105742392333049607889275325047077587703440330421505211095693165846272888865798145628128465649532183743436430302219485879685130624377534828634068671164675137763004367669217185466171673640113869571972527485330323008221163922983114135944322467850308368705582418698378864361006819681804122336786280588837594494875823367083789184405372515571039201711855961493716324895541885555759790545252929102253821916608045825739345026901929385083535594393, + "H1i": 21699881294376417409800665900755924607855855670777164525594884747871505860436584048401458527747050348865319229176819458906139168817633549338892633494898000280183277926615153606045417569676555223325154156513009493610161569156730603347324993846368033127485038318080813554790829737853831194597788969560955827133083725940330105452966831624601025264661984171392078892063969537929869993505691548330647116399100307514309562475007699880846486521168316081337945887379661784674800974698998166735285948123919631081224076862803882235603448438227781785250678828068068286010852719455222477410149403637800669010058108608998760509841, + "H2i": 14045465267077099872848911353415869460863433388841510094438630043097727699472371984645771640838725208953279105395419953463936714832196310885825290292778240644741480849190631151381431722344402944704343992122840084706958985855854416991000494001595046219226524756249254341665749930035053446370727134654485029198655751976037954491329471913399382151757160183485581591945941068394957104130944489169806731760196225432711453978532711803596725683051547253607327263442398106379278332532575664251055206624365389525205405464672459419262955214202750727615105909474359838259477824679141121088845694285074318402013869822602311856944, + "Alpha": 11675540657945590192129941073339048241378590363276767570520214114566348422538514829738242913638679590191397265569339769088927479769545905112188297870604327382074002672236698621259598017032915881023798429380592706842356172025027077729741946405231021153009012573242689040139285597946178390548626707842840764396825987471499470108699995120839398156000836378553470490543813646043919287879264161165710821192676562307331611229329295883376839144635977577539685537413784509612415632436572771620638278172753665628651959175248526400959025717050822894538836537774249501781230276439177750280210212463847186198652099093621526877406, + "Beta": 4586120800853186526677836385883223336623024330838240864931296211140077356125798237713667607011239444972629512979380289719425546765687644803735392053569296270900309021095475571738392739573155762439416686764948032693013194392534740893484152534600725789078805222410450372239650368036702655641816170991658153151944222410554781900960506086405625498002302083973472533288569560489570208881024238253267695392717979255591369879269313072357797527920254860523598286812751168616936181113587040829015709126323807254608527484409930223214353755904928473090343134881462903919637510986747643094430419200360171462388544994312968509327, + "P": 84054578351311302693424781277032012766796151045755669347860286706120907662603036334258691508021966088443595489972120155733160179799613711215573783739843276774531366311112633664224050457596970151982039165307036996532541062372600039543522792973744702644070173557270463081815335868655733979792520599000295694833, + "Q": 68415145981765838377841119041728920965351900492940917619585204652477525948198719482760018128253579869523822218151702834709898616250728914275815156891060185646337070264796787511378036640900230906289072866422669050633322610645119524468329955569133346210085941508761202694781807583199414501699168601728561266089 + }, + { + "PaillierSK": { + "N": 27212596883874729434568103787891395381478147365555964570566206841558945686675846421124058146878764081423833120340079467810800620690713761225429305094560519125415535652661463212251326026123172801450581162532443375010949832780654738845546552675468799672281558484974557758304949102489626938897131098740019689892770833199110675892924255322140172713413629773221681617537623229137595146345681605621213155318346774180250586055795415408051832026457920062397228120003308532826276281308357610791940696946878292210798554400662640649265906699298842993166090457152155656789632117273046093736050232841021803777883453375835310239097, + "LambdaN": 13606298441937364717284051893945697690739073682777982285283103420779472843337923210562029073439382040711916560170039733905400310345356880612714652547280259562707767826330731606125663013061586400725290581266221687505474916390327369422773276337734399836140779242487278879152474551244813469448565549370009844946219931899672176678567231121692817432182312716704420985933242712879092222440360114777135639373883154632881486056421264755204699046545894984078289678406302465192942553588430089990031003328348965881573625272308707108352971851572780194352109607199613420889171578946106543311412681700659057080161870313837716065658, + "PhiN": 27212596883874729434568103787891395381478147365555964570566206841558945686675846421124058146878764081423833120340079467810800620690713761225429305094560519125415535652661463212251326026123172801450581162532443375010949832780654738845546552675468799672281558484974557758304949102489626938897131098740019689892439863799344353357134462243385634864364625433408841971866485425758184444880720229554271278747766309265762972112842529510409398093091789968156579356812604930385885107176860179980062006656697931763147250544617414216705943703145560388704219214399226841778343157892213086622825363401318114160323740627675432131316, + "P": 178622013594313389023433891200657260619505042945866893592157216921859560740498110958640140361466759744227435610021175753771006573002715642352365585561569346434092397692364550806272244576356743583421146963936310913608801352501268114566326511364302012655785247471299514462677351097661285401121944999276586678919, + "Q": 152347386172009146766359187553880588429499296866972752078980586457551140724463265108301736209113705170260178332931710143871427360363414451888283177629134256006298776439132880005606445713823616864230156892108915518951161643652014489895544731388626802355503711909533492650547518342042404216437767748883291428863 + }, + "NTildei": 23561405613286540476604998479716854527179404892055553049717276336050549550734409416544202858872947871609706451634586610948338357714659159664842878598185103678929685312631635729408045761031477244246801169705654624097019436744272981719474966776960406716411037340003812809221158989959243577094726518052002325065483901210261925552352912567176505395167039752184966824720938709307821133440761657324636233080659273277098052107427269314804719647583954645964283806179002905698757289115077568348723378241261798747302826980045702799222712109534396366956098040842968621488412132100558390125582914630733969666218511722499137537209, + "H1i": 3680022766237856340975109583052310004088768689292819583082711834702006001165457655359816576758322407117047903367886413696014846946406398650500577339159017938492252971760883032305446444993838916510939491049077309184298771278312824591873483572833092378426781224665298521197301921323197966195815453715701747212722938702547056145624876412993918327605891117696669421348064888468594696159156641991328243507402153365054631812412367374426377907384297883279465053629878843137391101205242763862108608578443260397959822833706377489317183260262318587101728111268738677113267120470863510392744903017792234289675437847142190245598, + "H2i": 3269897520867950453631263595456214449849552190870472450461713796865563422680415689759993271068767282605058900057847624979112184723345205011470466074671598109231653860765422924143365180433074694935343018449304811868958233435148044682952535488744900103931244618977151592995640182572357060509995241876883592293047449621571569517763051672472569015141471017539773479774584582259182420782135525445086449808095366829864338651394791374940924002392056516508219502729480023372749161035420221344509315532561563704224537757405358227147920079204117980106269411289320654914491765443804054234079970803905817624183838675214797298367, + "Alpha": 2917745175648920159073152880686927752187406960333005354692767224278728938734975379751512036788911495151791206604723276421819142078629586899802601887956552148964492395230004821589702001703987682262592155246560287104749299090273731043223312742739482613136489565955748931706122181587514463273647057505221644450665530326213552211251720784492914925347296415052540122504690052369640315882131272264395449805433224239894623305205754752437135049601832808396519231572974577234477380435001863657595201080978174463401289668674873069865321809398031092568530060084760814800049893560235314693644452866283976032193325470602861601553, + "Beta": 5232006984381929312264784870746527167456075954903984059528023986970906431896957468374908262197774562774670035940417206033395793606604355545891583896487215903925937413795417688634972641467976499684649584871172549583821282541242384771814928858548600862650188284641809958578336920423520986540603968559472812033634226260429611898466177229333321455024013772311674137236075621264427897609179645469322447176669881676339810916235703221149952222126599460103390672760193166188396032831930564578013179932369656600447259127995211264938777713923011724178767770857055131035363395510793687061749944802133155630462492381101132358313, + "P": 74934708086806890008131700647054424983585543887676780479609166066126441023833047480275546928755973068280164484665910023135992310492137412132301948511126434258536775917297865720363403978176559091412568041018539959665057225235240825539586574501200756046250265758123186876041155537500767785917045483139536065431, + "Q": 78606450251304824438050192256636162108650971613311862383522531824117739545996591669723210709150539191296668566091986620823673549756312585851727293683679703000318092219704254311993283030466733516696006621391164543951009462153354953436790423344390208926160440719434363706659111495509818196300416666027675831371 + }, + { + "PaillierSK": { + "N": 28246665701562306947955972214001672778817491919948552318723903271549355595609782350955414664253111821331386802312415557733387114327984317509274464360688005558855449343413371760962710900629733077881127193603290564608865626508409211100133158229459864243259147272818277327691430028622555933235596964285949156368162370208688293734224827524038275690085250259651612191608672251592291009963928565888298808568179984940193917923296196655955579228578434578310584876212982044643443451603009878799724039461504925293833108094898054137744978925189278706586664158876368398976731084963611245903204919243272837150546157234718929762509, + "LambdaN": 14123332850781153473977986107000836389408745959974276159361951635774677797804891175477707332126555910665693401156207778866693557163992158754637232180344002779427724671706685880481355450314866538940563596801645282304432813254204605550066579114729932121629573636409138663845715014311277966617798482142974578183912967933512356970153623262364704974882421017534514435790814771166979294743574806869463290600415393456281953414328787414784349473214459907220482754055901931909542918224709317587053194811051125584682290570360967775588614251671754424416993680297793178704054714117565339579514123861269822721994573832461000379358, + "PhiN": 28246665701562306947955972214001672778817491919948552318723903271549355595609782350955414664253111821331386802312415557733387114327984317509274464360688005558855449343413371760962710900629733077881127193603290564608865626508409211100133158229459864243259147272818277327691430028622555933235596964285949156367825935867024713940307246524729409949764842035069028871581629542333958589487149613738926581200830786912563906828657574829568698946428919814440965508111803863819085836449418635174106389622102251169364581140721935551177228503343508848833987360595586357408109428235130679159028247722539645443989147664922000758716, + "P": 175313004897583624770654108558009244961061558660290841981063381116459289330674437060656168641021515383957405497053702262092418083159000201288664248661647216052609219519755546139520372035676567774078215753295465054940883521950592610662854625365010310152970959512560632841573073574790288345056331552333532362087, + "Q": 161121336765996169146926890750856495359346665922292478045979328141873131146104515088716058726327682643672605597584919564294462198990514562580955119439530964771748395633835697486097277803726106350390311200880653531626866899895177247089822172915771731415650697215919933902603597945942903361500678017463396641707 + }, + "NTildei": 24455428190484615808370825213440551423980455562751150477446776498712840787993160762367843302805309837379891683124532741594302901438051817795256752775997988972581446321914362854151503792577618993191020796324855902478027116048353843732297817226180192000632671970246037527360804961881567479302832252185348739381459051802630563324121821817991224889087101889661953900214374135855410245698046800574083075532283114616498127816597564179155823680216938733427411686386448900024239920417466749642036400913337391437874401242767589142302736450143968773073556573561296426280856094390845646531530152018188464648918530500656448558453, + "H1i": 2057088929776996250098876489788450503037778688238076969000975437343285626031519342706114681993423880369912650779591138497866868500172220528253788254447333310546742247093403262999710002644705552186797302479000598190750997620622168886629423416538543154758497332155649470894461009962413509290077040497985575283629104045894202658798196672286998907041881451562246096561676930351374680248088561034234710829253605649331500229496972684007981875143981366797542286813082670823773200626725705975997438243143676944199756328042132000271152941416274565873588991910602770711303246665767366978419907847752501009801703544887330518673, + "H2i": 14955149280279485355327723243130920675191247906217604510150262732235485762376598307780088891512941979917507258601492629432982981126845154531437123997944273242043059092407643809659135918344154410457538465146295827446622810479929784603676676921306007398690568055440957573203138744398150997083377659994985465509160050621382309197553322422400412548698140902866529322437103587134498315712021069817932634367552431564485944327260352539707896567125313643152684979626998332365948235473522632460779195466019705000231242295621816908089362515522856041207340705305178270137502837138325155321140248840315936862316448405898759410199, + "Alpha": 1472341738726285674053363041243488547263891480532502535654696821601943643135015425439238145173206481485067838197278944256576781205047678452512516415556678553629767291252902850093558200467041305237300552042314305345324373185503055640161352398532298919288546908045846260622647510036782439975474035204590195708904324802546746399409777898802144014919323505165226774412007033398110170367492208517951509874386605878782868935823386607206768537633772792312894499450049680254212082669080962730054522850552173081160056851332588781016282624810744081230062874102565776199292457080666397355988504022263895208938675306003663663099, + "Beta": 3091756977564816015636059525046089013994155743954713708378071824763482303258500081289222459656729535414192395713288105459032267031370275005499884049502425118758424324844028993991773087512324294379012133748940359494497257805876041207781145910470972215843643089783898715263555434483491747717568971099888954323527191015639214047755035070770504060080843262280074392265902716288435471467038505376049806023351307582522384491339742382195133066920006045382560179989771519566051275293221388881172196855148990219145263120770315303437244469732090591982691862032247554610032904400979847571760779459321240297037032069580720350442, + "P": 82083611096124572982649810541028022577557202288925296507342766296310600134440215813921866305471999526214870838090350133242658107918488576484442287832548362991374109795394867789210732521412282324606273272591711312549519026296051799086511875190172719873306596941867964059056595211834666106731210320163886185643, + "Q": 74483285591096618913412451178553608486450949492707264176186074553993788579508683711426063313058961145304752779149245641200683614526655470943667795778596581140534555652452215245585480779710942611904688811215929423091269841831286615533531239067981873362530481353360988769814284637802931275533723327804533696009 + }, + { + "PaillierSK": { + "N": 25479243749626469880303962162837710303937541719028387823221262528949364439177460675501436499751390180000704377585232035693965743696644273794327015496396390717130191959414420378795621130624035443350184319933126832691470613952803722820316929286269793054394655733261854825338000882186756669372119473841188398981216078992641485543367075645363237572596115885243079497744457656153434117797053105475173292004913386181315470911629785267398368401433580316127205858718371565996226894714904800816890597989904276420295419728008542659245260905726160467065636086838524258566764859726041014762716301429109342392595289678572830907469, + "LambdaN": 12739621874813234940151981081418855151968770859514193911610631264474682219588730337750718249875695090000352188792616017846982871848322136897163507748198195358565095979707210189397810565312017721675092159966563416345735306976401861410158464643134896527197327866630927412669000441093378334686059736920594199490447832727814277216595232683937757152722633518597472153053042689222911331600617549530023971342203403448668405710080514861255334324792148142298716199732086337617095472679561347945752842769661206241927062604415151371314547354124638857760513248665202727776601741126747602584995889513779956893572580753175952793022, + "PhiN": 25479243749626469880303962162837710303937541719028387823221262528949364439177460675501436499751390180000704377585232035693965743696644273794327015496396390717130191959414420378795621130624035443350184319933126832691470613952803722820316929286269793054394655733261854825338000882186756669372119473841188398980895665455628554433190465367875514305445267037194944306106085378445822663201235099060047942684406806897336811420161029722510668649584296284597432399464172675234190945359122695891505685539322412483854125208830302742629094708249277715521026497330405455553203482253495205169991779027559913787145161506351905586044, + "P": 173880280332539123970960693466828164625892457202723984619410309088532664610696118303603857908223491139749699615192245586511461319317545335288384072362013893057900469975944888816578354115040056521359610594946689338050012337410970633393426123208264778486217193864507237451218368679369414804137859122405130152183, + "Q": 146533256680391986205649584020895102524956390845411207018961968619078789985121888111521491412283088144228959876276509958376238432531738696241389386892184997704135479379837216108806558335541807415081683924231550578566153860065912118151183466299854024527344183608038572141506153722180013801312269049815795169243 + }, + "NTildei": 26393211866117610599753747728775425255461566210652178559505864044051153079520643670787521555812009867195455990272556744881520564400197711841351059462452719308362206305144283427594953287915821638203348587580342287988782561845411091498804613323392976818440385552880405167164975555592843305692744598217780798236585799903030965217685488172780248448800495534478497244966900068028803427997449791628872739599646894897846561306065904503367222347350262880152926785840265757414051460734765737587172383089279537433037409334726391349437001504378838298933556069099211235890614864857967040355422106968633278558432654391495841145497, + "H1i": 7371327340434187711375426891572483758173950399162894114953811894632752168342570179558425317700869024370224195076967941830056810928888546039656050315068548928874030710004062004983225275858883022406553279041730700708428436820530227449519665350573217827288178221432840694897044527459923130511125087937996787887133979848380440821657189519736081580112799350172917833619188245598967838176116052540496813253254549702854437838396259961048648046515421577721542023970129496253142468933916301556135307316249076081846054295515284313633081208151354020187486499183606777660770552065459456769098298716541633042864480531904742847729, + "H2i": 23408883372817245431623821039748529464984527453480266166205919826904647746343226021740845608762592121575756044638369259413208891070461705476949924798223238057318087838184778094106157350552596110169626035988391683114841768799301758526035611704996400436118893721194878906463787076286400797103582182066604317012892105300199682020894457762982987965093791862522375759834800827184017709394069639117083090241717897108726838579016816878528299567515091051723989531665945622577591218494759959682955448428323211299676270038764002300699888329429244638339760607070589670154087659251513412707998933888700819486469478901912226889917, + "Alpha": 1528395940989684048015606209941777606039875574018981919592371235932931785122467103945339243480854798750963882320708985426604891556770245458306396052798181649165979434593306550230643356388436183574969889929903164750884784108675078342462310074862665006720383167388116393013804473809687986888586072918134402740825587926529610482111478280521927665543149181349548366916363242880538669473536341437052887674207205258510446651873695551073980627680479998706518705517590148033611800409208741711667913538037149930564050925952095500616035091819004046937962122055489794034756407915178880859265882889809716513657161984627447031116, + "Beta": 797707395386479786526325845211584604236092110930797646485236511963945246019295642777459161402469302485638646347207848673162277867789248043335199044820455980285410110627439613987201482178158329910763268801278321002047058506857802354225565174043700323450942256465029605112460233703680611658821091995455247823998934746536033588888421158539414385200668283475000081881132801045503778833550980873242289026436872491897383835146685435877788114324444001144223621776940876566654099531851906036993489200946446443842623346307549331473973074198775196464802975747474250313863873443102538832860187816904034667478927615652898747215, + "P": 79657221346437685022787088408951447504148494431944620730288688592082568177394726488665307453838354488567635705737888977500810551927416534248959278698336018184295851326056669019390599630807847508489118683427018922514923983040555677747981022193931345026121380822450554097974125910468846563442442294512746154261, + "Q": 82833707415335074407314325478498388590727708217946677571559792243039843306003884302544335031456320810546703359295509981295230385226699056636545991505224286130453588674665414955301118361206386463884385904268088780407867937755453681183422255872195951793246122283743196339631521262872267779805363250298497144869 + }, + { + "PaillierSK": { + "N": 25252589818444451042874575455049447519278140069243037387677852557776155581036454973988879751297357336405166760276018499926235092787916495952378434506548436481288800395602670576493553119453407929865738270428229477528236953547298028772017052351368830425964871933335601787396686589854674799895953157191915465557578338757388940291974111656244957932016659424705780574849385672801575510229682264178882774469164725291154623296955135215895102210119878027158165685196263808438763697563357758757933078273361894459359896237005468662383867261829444259106293759461577134197117373868064848476506282685146086302833260104799689748661, + "LambdaN": 12626294909222225521437287727524723759639070034621518693838926278888077790518227486994439875648678668202583380138009249963117546393958247976189217253274218240644400197801335288246776559726703964932869135214114738764118476773649014386008526175684415212982435966667800893698343294927337399947976578595957732778629940777714003734332254217259955070833612968894900846252127005836872862855508788916671854856484305748063688834146514993765269009320155031554860755929270408023477382134734133619515779031348022836655519277770819599239464969638073810365713216651655048008768898807327734649684325867590008145618758077496595985126, + "PhiN": 25252589818444451042874575455049447519278140069243037387677852557776155581036454973988879751297357336405166760276018499926235092787916495952378434506548436481288800395602670576493553119453407929865738270428229477528236953547298028772017052351368830425964871933335601787396686589854674799895953157191915465557259881555428007468664508434519910141667225937789801692504254011673745725711017577833343709712968611496127377668293029987530538018640310063109721511858540816046954764269468267239031558062696045673311038555541639198478929939276147620731426433303310096017537797614655469299368651735180016291237516154993191970252, + "P": 169286312039755103910929642853129564327456797629864262245180686782684274478200105078798677564683342993774837870404737823802248850113540021201687179076422344266367223478013815593031548264232872341164848359956901370091881581913820490893091743832171299815285139001003879405798709161493312811362322456176564844263, + "Q": 149170889921177719398673578871918226021976689286114620099950974345145510040464581266740387191512770801252407758257367404562315341366027942846756994261300648125441709815875675925869971946432976444884009321506928093813055740639476147481775582326095738364294437252405499771338921788472757200233421493629932934147 + }, + "NTildei": 27427949615470901631400987208767075324259173811619071604281178795965441684595714230361253731752599571033116861804651874076807625414175718334037017541303491611565195594055360133291209358488065000478871183667646104834575239418270508555406940396413090565218860493732781246178188853088803947949185051580711421997603403771915372372941760511292326611244204234537710870598336539377716423026031253915544611200546942265406072311351849575251365150129536095302042977526060410702932875750239738236656240320040066347604470654327857775150476802880365121695560100421410988240942887845816535778258824341115007613038602995648085094961, + "H1i": 23812814745454264813635361115402202228040566149273261312371779874909366954182190589803623422699328381728167192296252747988409671331446368050378560933618922167863613591615054492567069723567794709590689557049867910205993321974489984469957935400531674113401893456623967346272090958581351519762323277589449490680990380117519476382287715007860938182388640933105458732155442043054653789880844921644184794938360607898101345841526480504977897720108416911032567881673084269631157208363858816555494386089982977600766660734229004691967383343069572476709107270996257358909609200053233619331304782038100517403432765681956263886393, + "H2i": 10610017033500179156909701073229414381487012876312540252355179159713631555568117664635061976226421190480292931215787669430768659803642960289527882201280049467990618295300728852164658316721753428066589551437386120815129086041984793265894581456712260954907812288081395577779293589801097796635570253074540245416644185309398175850817603404201280726921490752669079118974817919949545183043859926014637453835738239560950883352945056848095728299168850348976918503174825406429941473994819618078410365910701442577753546434727675204323169361789917359185831859962065632928549993484722339698083173215397920643234312073778202540208, + "Alpha": 6068115454397878946500188671053184170561770081170879690352812342885863933217220195233805231066301121925608356275165315579919344934622587847529530791307716500752491745048590813884593227379705356629048724402238621567551413606483500103923814210758471667129262643157391949915361243700775663301135951701055618825853790573749640502160621479113227640739376214481152434165136254078483734017052986617097285598183279750658283316116196443635528930890348204124349836882082795547712456819373753897911574531153486028869742067148957922545654595537393155233588421750096967560429288289479157360637252551087532376488890244181344284730, + "Beta": 6558270197509051242355826865088321698822154254758404744415769548282781995645118299731440407366561165040902685274031135649550443255545587650304986855842229616970774166127479746090703636092867500591479343309064149375509484386154321834207587469619642299277656618536010247084389419508196391967534914728341485278111726776132172545046816287545687477947244768311593855104851443900122453083668695056126680931440065320175671289312035182740753269034388913373745339609637131817932420197897571131176954144533298095741660142426773486811058026257591560291023319872300404742119687808375376681821554503761714668499187363968750252419, + "P": 88594306578076746831430526542997088951599817936223356660689361417437430113519528828216255660177992698173250346170112414321011668306115015023168803845626120504285335226624023098185919554720261503739950027002937118732546162249714772379299288312011834681643103641863335122302432559492119722757352528346735173893, + "Q": 77397607913153786800697115122332341790726923909878450867868503237218148823466099959670290371236847346581396730911494613079769097549118191239972670109013980353995989907791303339929080371543691079798846810231457296544247623638866049187036310405194238890888306026406427215003545476629243298914044852412739653401 + }, + { + "PaillierSK": { + "N": 20789640499942298282823351484191314766096554305460362907973136892553291504062726704524368751297046204283013517317380196230534747422116172322678957282950409332529768725499971972515080055484260166378082341783116741924883540529624474685920251986040557837278896518281874278179380138547452808150262593041398913269140390676996278764661044288800948460136378202462438604208352902115149069653381610853281870718860057534879862280740240711466876067629607925738866435302431673185628348035093030131337482357933893240490368949003024829215510185252901539097416387084578520221336916554743577117834908070622142419122265336473515947157, + "LambdaN": 10394820249971149141411675742095657383048277152730181453986568446276645752031363352262184375648523102141506758658690098115267373711058086161339478641475204666264884362749985986257540027742130083189041170891558370962441770264812237342960125993020278918639448259140937139089690069273726404075131296520699456634425754333330618610372455099160247396477857529520193623218572133713734903659920301873421112883370798413965205680379312255025234655272868111672329207892141265073347535277633039835125570005930098418811020858493137463533442355734213534524226702578770471309178299093560003759432860790299321518034046364758528514598, + "PhiN": 20789640499942298282823351484191314766096554305460362907973136892553291504062726704524368751297046204283013517317380196230534747422116172322678957282950409332529768725499971972515080055484260166378082341783116741924883540529624474685920251986040557837278896518281874278179380138547452808150262593041398913268851508666661237220744910198320494792955715059040387246437144267427469807319840603746842225766741596827930411360758624510050469310545736223344658415784282530146695070555266079670251140011860196837622041716986274927066884711468427069048453405157540942618356598187120007518865721580598643036068092729517057029196, + "P": 135864089995883357119602450187001896770539697930802077461948643311505839299049816349709622437870878288927932337516872113161707839501741670803049172230932313957191922052710381961884830385328854878637504840666127368447288936797427472026835929242383512194377084956830093972804489073838931190636712102680875078679, + "Q": 153017920339158186796531640293451770410123445491249280309259991376173423034491190756730022514247582418021518582464744088254698917582130031591158847287216829081741355427116568499201511960744841524230822391350622533701336536987046998022127052684654065408603233410793475626164697416184568192417460504275583839283 + }, + "NTildei": 27383770483317027957544429693805573196572439549819437357507509369021097516488665385168493459536004159792286650289099441312297643630074480980368205403549136873288008058123813043145655145730583472331640725287658154064706738976226764544453413827365410082859013030604969547458370262271167344046620840914474765655776425025544371231547791153602456735312874616264767772741174196913907322184414646326109683309038148872550285383028856028873512050350235429129021420121950666373968531365856539646264174753341847409019435612727868705162170200344617293526694266822600254062481438876772460223606571540844131616873191255835320796961, + "H1i": 5870122117057908933416424711289193004009190105370048825714984621687152560716332898477220730836088586756915400023045618252055822337706817159535091668041743956324118324477556241823782255444631130755934913799229374182784505443208818305378252084954433238605495314428702132475611387388629679317219877545962989792675430137245076827170325335772789889196461076205055346926249849559906833838480966553585295226099938312009716350737862011307808765143716122764268128292492269749603922936139286734711644256536679883174894111207308418397954528394060197087429944501689764320445866630249612465757075293065389131284232395157260247601, + "H2i": 19367217373650583623355199595666870337928209385852582926649720420103734510104200499573575057213009158923275334978302225563068792343920096051084772113486915693321510879966874835141400609617511212772108749097427999386359743305718288912133208156105221889251886285684297513196797224348010520152528655662910900414361536288689655272859454845352431975773658425772508978513272673121457894485494379191587613445575335076547253722487675021029339236177080471926357213264339172623729843964670601607240117012053222388892556253742950090684684439218889352577746078690140252785268305282016351300553932145046362324347061405808506639132, + "Alpha": 24463260184082860254587319994513308777916991116866545612700219230526339667587178297539388637479992140514835776412230552954097304076419923911529451704823351694180633479027384958081029795210506383944915850144646263117289922333508541752465460090174210769291936334505582484180064673264466507694032455009245002516608971999724959282555560991595410651702500881051810427903705028569160244719372262673509157502820998018848617116127233503846236686911585566817944331625835737420097549659515557998568159304210128544826999647917179404482085910432794934910287092352665521356390726220414954253614774629679845106622141820237657346778, + "Beta": 2774378631950531070764487216323628116269698318781503259888730819843320597730655156036340181861895056467054877709885766811273853270187819356618912306347297385954139747338713542148524878182639921954337756868453104713686210498455349862820405729108623421661749256949559079279141302304657465209699231356003565953044754471106959867044812204792741558532205029650340115133543145446691997845005004923711813409753608960299539146041394246481299325528303237165857825003331010591005560904546547530227667324988111601125634837963062373318087921678278803669458390818639753049172632768826133593224486040662763347621295032286280893358, + "P": 84705375750943317829167000294395499027853486772453947320027042645329172761372880749980896812747623763096156680519968497986613241677793043544254556739202802160982180780446397969176856947632627646778825053613525859465650049301048229135669576304040286278241592311820435408862171008886759392694684798531748605071, + "Q": 80820639305800109615407389611676731354764332460804712558700191561055131611113343659173714248021775382551239207824869971781141263855314425358132372745331069701889754177854147705858432437235283884301409424983576099901961256135630165986408078060982090785330806464901802021146315630209290559673832709301056080863 + }, + { + "PaillierSK": { + "N": 22452818887673591415844066529698274193613692714074160848471173379475539476659377479751485760447401739718781153188204563440616148090155544662389118761192768786809694997633466718141961322249596856272483903415507847944823524321013255203492926767612064412074321036020904943588704780176307083396436766758824850946934208863185603183797008530608840735119015592816924356787336123048362371934131867165415640586223759698139986828113285662382802857339350033062991722668855841462255218546136723663863828976710000070573793365770666862090904271510537580715707044535625983528255325831444205746741658827750520434158542828067740402521, + "LambdaN": 11226409443836795707922033264849137096806846357037080424235586689737769738329688739875742880223700869859390576594102281720308074045077772331194559380596384393404847498816733359070980661124798428136241951707753923972411762160506627601746463383806032206037160518010452471794352390088153541698218383379412425473316947293298420438369472352575835878476679047850988804109826607480812518109262061771975063487802174839472518103024442388315831697572842901080677033904858644122132935898318896051001361233419035732546988089576299788161799235880659388188370980971857069488180166365039898206097274137153616334051560855302436452186, + "PhiN": 22452818887673591415844066529698274193613692714074160848471173379475539476659377479751485760447401739718781153188204563440616148090155544662389118761192768786809694997633466718141961322249596856272483903415507847944823524321013255203492926767612064412074321036020904943588704780176307083396436766758824850946633894586596840876738944705151671756953358095701977608219653214961625036218524123543950126975604349678945036206048884776631663395145685802161354067809717288244265871796637792102002722466838071465093976179152599576323598471761318776376741961943714138976360332730079796412194548274307232668103121710604872904372, + "P": 159870391770138679590951501912924801709432928181704706416260690211286455991345529765734711373819683225187025512998188016932207274434189910528559889631741437963377649318177650275612275557693480437379586310127286656631145563998513779696853028437756241868235916248369543669439359809284808075955214411143245481727, + "Q": 140443884818623627467112323544244176456224568933242042151422217875450879724262213855730802236799726794007925109066212868818932187759474320373077765227397115254611697431321281286248830952178448168100230876490780629136160235750705024642112054154155602683659076852994865665107750744158479690100206706319622016423 + }, + "NTildei": 26721269687059982619263305691645836651272182163634293798608244332260479328530818177743994672658433328797530323564529244462395937067447880750685056093140513104243452918122522142107097576190561201170781730336794665542858740868165021207840027800504669995850368201896386081290325225710692542129643836704094990044956777168433984777317740941014324614328237760771796230172105749127935855185188630453341760096632169969430174871994793279861890981835125770645823721458758675348165600314313187070405654462012157912741314098970289822633224338176322421119790564763519684927002003128097211012640096157497123647488069731983035323381, + "H1i": 15921481532188214246189063681719761773498423722223607429579639620519021937215811463713384371306447774918655813175361686655015539508271755044748379997372362875038261274076259825976912663972420333452511995021871532431540143400063621154399538451589747522242780356852253035654112806184272773758149081272448269820457091153344916140785392340275435146495907028857019310316922822891019170990110350518076108986863791024003725020825455320933385149474295486597735154819630070696909420554298772084399999486007903483361054159978945904521435261125987294124403087997788904786552206667557219689435664524586169734032304675624533554909, + "H2i": 22120415505787583100414221311871234924838436080303172132326115810190601110545184348151888600565570789852914511428014218699048551003007308883950729513271287958881143859782984233996178019353526662797569296896168086740728971775907087192500654569250325855299576770701120855355739560656795077620926026101416815721341054634507925839238504242343083863765906102579833528994626313229865302697474896420336039301937837401275492812695209457320977879743127805128817350821268286179543427035513512243879429630623695312927501414887640529843654490047238822036998852659376189087292770826292863156998524687055024411536866136880356767404, + "Alpha": 4046794565045221595160211067657300747068481817185809382644642570700398634901779522698402606797728500843527688051764149262928543577891552960492069265026104230120321289494744698062421892284691761643189185665596592879681559164002257229279074949521070458506358067539376239447121967839466922736795882511210465810797212849729736981620846926513878495652895060298748099516240408411881708253822245054357787372214782428437413935532338837234420516596149018474199914858387864371948443476677008550047594522631430760772617341887133843440248857056402802710206224614446210363870787585619026326232917370899781727598515889704494958728, + "Beta": 998515606112900320368973522517486455994006211341658531315344410033333341886327328420214997836134664837043716186677516012421311688093197585496278741600850315434332691104464330390866065306665826214105385712573318465788805373819442731002722574038533329058686974915821884066872840417265503377220840450898870198810873993918042814031256132695745938523513283002986060394740109200165294281838618750967597804208790863090341773689775832288650595486098953673796369896198284498558730857305664117171797769338610485926246295238999650332554642709846630546943172186060815480735674721574223678068632042334121237077755469480576513291, + "P": 86438935223080254461231834949819663190889485406785969394472905849809326153655072734241331847186424955996708200340903419815538564241711576233452293817525440198815228076786103003417504157537212497814292181309998352530134388474643358087763904918093081297194888791057402686667501872636704502740887945190514744129, + "Q": 77283661633782701647768349893835501718145616449137563271558330734783424149064784883372376067698259075798939980223753255266432453157027558003380650196732559201489926878554650084676126297113849694791308278225133643216585878548214798237902131555291993393941066914270122921430084293641938889385203434082989768979 + }, + { + "PaillierSK": { + "N": 24584382908480975648950768149379041346347033237675911038758584230080410652227656157991136307550002528100442183781829289795947747099757937722295545032622860443292139308252031978958388592766335342408515928320254955544468746408413500437986007203137659374061846683321952311722494263061155311628002483601515451410342819605990734756463117392496537917431190419684017852311540722979897991431897270146348940033322842196904263085593020935717638947312564483576306320463960720088884610675535838708887447460471119870753982784418653199400290117813775438891101133626589213967200750299433180884572782958371221638230630488551868704877, + "LambdaN": 12292191454240487824475384074689520673173516618837955519379292115040205326113828078995568153775001264050221091890914644897973873549878968861147772516311430221646069654126015989479194296383167671204257964160127477772234373204206750218993003601568829687030923341660976155861247131530577655814001241800757725705014501967509011726164773121187801171119440006279950867227366676303140559044885601964869680060853290550989761173785590974159268568457922657007584723545531789389680927189585607485007784138831851248252458543661823250630910138620681381584523485359688663097132676551584304151344450347592341685202702278730527658238, + "PhiN": 24584382908480975648950768149379041346347033237675911038758584230080410652227656157991136307550002528100442183781829289795947747099757937722295545032622860443292139308252031978958388592766335342408515928320254955544468746408413500437986007203137659374061846683321952311722494263061155311628002483601515451410029003935018023452329546242375602342238880012559901734454733352606281118089771203929739360121706581101979522347571181948318537136915845314015169447091063578779361854379171214970015568277663702496504917087323646501261820277241362763169046970719377326194265353103168608302688900695184683370405404557461055316476, + "P": 162881605529826893621658234163768404895732946798002171485839351414792154677341965400143391042287149958157228281641680806903206734653527622549669771979258012555980424786751987531850581034586312043853606316886740368937897517844891534394023468161005715881558306550380071199615935448237684412853236561647765002983, + "Q": 150934065442884410511912915957167170296577460326113946370968018958824718664784100816466188869329111136767512456380158180495895075743191547011467101393639128753542331509612636207021298148221105330395459380208266329200572322727521141328030694746206171891377090645884501382267946814948853854971989369443048385419 + }, + "NTildei": 22239087147767966050699589116041431955280653644672850099055689541691188465736454521258527692669672894323728650758836626393310718162312396489457423261697556645924038351263137555752777948473068824708730731323323800449751020800031320602068024435028601498796468713911194053070463374097864933055215266307400137058959601582043270934384187333373894930895829569538972533233676194246108490903095108579653067104015690418699912236314919343217617008345840256190492995260216954011115345846008288106555697444897871868456547415737232288528456054026636985518792071282450649226874625922495796932551331326831219153298751030102192568397, + "H1i": 13297114265082019793261587361825196699128448520129813679345313801765729953078230242120463541397316436177333279264514926130539589658398011035796262799974728764262331313035192552415447586545393169929710486487146651473043980511777242897799637882464522993480483761323963100042615900197153788543524746187822412625452328161193061590439014570190106682977219564994199860754181519670974889730361096503164891326953462146338086339029470041877961171034768476322729120883492543930411585415881278843047659867164706511949307283676643696302319545570562109793049723320589627626853900539170043707223809262033574742698460043458838649426, + "H2i": 3654183955562437129402143109282543443638072794674639476213599180401299693584131386018263855489609092116479987247495370441323539601552512423556880653995134967145628986385695924455845525363889174573893398867404947657327357658098991011122622451120065504901559511809785788270778894085088011071947083294015402175789988770237835214278915800755266734726076236649591049242375350063264336658041350004572716412279621503150065399450803736791449418093102821111278412053257812297218244213590612960748124102587067026044684827522011973680152208325744511825710747499216101318985398360977601219147531267687832542218487683744511634281, + "Alpha": 10118087064614406614212679940429271500859025907160293452217731542829040353409262644125021064452783685825208017997202849302484923922880334507510360432569705086478462815812400781952100181143927151508000887982031952335637980725312490850130730124860801781172028801155823715788161732681250899173268372535923827587187850999313697451235734705200601101198957700616602862100960919397857021651101086261212763050534157415434566285431025684241260239329229522783975903305701469186006697684422141728894564144300502466476821003823790318470736493523281544414637617666110707790816929388202000209134510867045060275602224932162576017720, + "Beta": 778000338768556278990593993918718971311826203540745019591493481325571340595560077978076224860992497205312860455356380325269746458178715563547298817247298973522967256243071754848756345366620964779839317678600258393151905842936138269522704039580561348617635701060521254167347018741955722241724875978792777144060509094183349312708014479697061225922651065670797131345735061618503122940913579575746674950841607069255701321852053533153495491542263122143661508119600057353161021400370905218122412914976434985620328261298896469955165596768869916631994577404102744880436108848556890992093812806812292982615934668005894686861, + "P": 68240525539265748317609076099740898917154380874011644884016926975733749952333189503283826761447920761152053573150839155522906912799131463984738586970770718713881256096639041863378262363329421001737374302581979601376202390161567106841790696528447370526701414047977216577094845859190882370723540115470034281891, + "Q": 81473167784191325018775020719628860678926559752873569259721063253720716736039982722971455550952200374923355780638334908894778798278515123977507809268971930287054823553585741889342054957373657057534809163559496008873338693690683795887141374662781125522949562356022006062230100579657810419679685605146688512229 + }, + { + "PaillierSK": { + "N": 22605584510643819852971604668595277832111790967967245452622811607814874311878641646435377790111674054998839491510576161547517892258197782780740839479700966875123827589727367273232713501045670069520587190172852803051326535228934021631018199856916872988543702014206381912395731015258334220165830445967051601848136557344699445375146811174217565070037237389374422142923402991326075601107512858936619051580699414344536992569678393864388278371052171728212346129858415323253048875402370832935597623682497329324963660047695353893414384449363058933019953393590706722308709744286083489989752845968381287016945639602520361454761, + "LambdaN": 11302792255321909926485802334297638916055895483983622726311405803907437155939320823217688895055837027499419745755288080773758946129098891390370419739850483437561913794863683636616356750522835034760293595086426401525663267614467010815509099928458436494271851007103190956197865507629167110082915222983525800923917206998115756717907400118918411474188090911674401591151298655340943715246732383233429990909851462548275155048759308451222921566949459639544523173824991634669819780338175134911985670018848798478559526766297477337933693636553567517594133253450435618923959535579750424679511374214194224406749988206593596309866, + "PhiN": 22605584510643819852971604668595277832111790967967245452622811607814874311878641646435377790111674054998839491510576161547517892258197782780740839479700966875123827589727367273232713501045670069520587190172852803051326535228934021631018199856916872988543702014206381912395731015258334220165830445967051601847834413996231513435814800237836822948376181823348803182302597310681887430493464766466859981819702925096550310097518616902445843133898919279089046347649983269339639560676350269823971340037697596957119053532594954675867387273107135035188266506900871237847919071159500849359022748428388448813499976413187192619732, + "P": 136338506033958287858578462113872137930469404074040812026011016972405740973092004145551756581163890460833450131086760877267498346781850253036878099376694308854343899962636695804944438644919566646139270202781775553651404922384939487637249394638033544525717886385385780695676984808348213131727417082840562524423, + "Q": 165804842433973651473432474266869983730586161951578148594794663671782429640956088324207313179832598787153232341073016084674936890371402196086421682831737745059065414763383867306681844999880165721705336312318623663895592253870984410194437492051801939935072786741196859935053112731644625071718246106492606310607 + }, + "NTildei": 24120622398157980596958920318728877494533028551150162111301680937400307909155373319207396398123543078505347893991079955176367689875915070210229447682262846507410968532716761656551545745840716239937036199193287806688693658899834162351813747761658885772979707997500709468495536232421528988045303569234920694924604596447741879093666520593639835528925008579733669507956403455954878534887822602453148273949029534061121433096499463691710883340000982577970540106028123615815077512503558200598077160339936356770797492336137599231646017011532226515194028997932473202811004145217663979247862125983176865984280298309953100043673, + "H1i": 18977219613120076128916593984852791179219907276548246096260469902584307933067498516740405172890306683937710129019634306097386939109184953729602461136874883011546212304730033046200170822516554967799879454573371563695510823464401764512228392518185896722701011255598394649245046198209539497127222941366084493730770883592511668925476233369973798834465023815926826481155709918007130476310238624938533484334295872943437209846627250638794073764166226854132512065747336422854429222291918188963946367003132467251507066195818360616075639046082603340605897465295704586934207088761390924473739686667262940994981221850789868592535, + "H2i": 18022927234925965267245078806516216721692469966403481709632621984248647860277712747632846962218538874163779731658181813241755594412267194294432612692312663244136308141566500041174089392700232020332767256578544787936732573293148151765379653778256558203147920811037486757748124976398714215225316950448024033354820246294306224868356474020247458765812576526616195766128077826952857354516175524023208956223932191749687374152958320070762804720526851582440892149323581758209056571192890273698165358058263447636324848165997064032045555234546782419781702841499221198083492008045860824389390765418480117940541868854377524794121, + "Alpha": 13429315072264996346484003951603612009670374743004456239896881496649991485006083133053267099296832041868659232050938083621021432605283411821899203549114688654282419535756586380381135043568278245442187653505338899399104282687239638128548160145017571119757036658682156396289770456721557582169335499726757658945985537595340154886393051651633894536467516640351143490032161308174482530604997871016519386227080029697172071237421584393165036472501130972162011188278910247960703899199874849539881916319358293048544262894399481381460612630680045052594642481485524472748006840432260902006240908993877962047953254379128024007089, + "Beta": 2978558682769694186109119794848672295825936301811076729581714961902508724568275346435321830192646894225394397432404042073611276719398287320200558428250986906205136983248355680221319451977952019771396698751222559126770049099992052858226673035463289365948412453176467400834728866787633316183288460010779343009693479323438733142592451879365395428172440382922104960817135091745073946259509275434653118435620313463040838794323391702885266047373149475968380708991429244602873915491996473259787266034368302496075278685362083059731555394334054432166579542206552824314719331915178594755396689632089718542063457799924229228495, + "P": 72042761095723851257253791541791348481905297407538949969343684113914809126878570938145121811850400481552319822612064342684931325009460435748586415401638034451837543701396889826664928100121273742973467228680539386201617465102070039490650931382768928606612382092073550411785846595678164616207367963510246671449, + "Q": 83702449875944847358738019979177126784917981002853998939238296358561334863468409270359739197644602688262618846006806144814769625740019511351181136815532577823822700693625170070460887157655940060633469253550905567196508009943209673320500631168979920551959334446632623145890080522242831158774196818482496277313 + }, + { + "PaillierSK": { + "N": 24740692502624148665741448924259677384674506215958266677587350648073289748515208909009326802475640446771166282904712813665456754146469422056929065340797679649080825246052289427872204122744058115682803292485153936437103418606782303678419573876662199949507500531367627088352628865895730977289279658158516302712501274044805028857652673141368359274378349886731940457118730045941218847530030518688926705165955648772642590439456879121175920942922844595863429440120380584527065774044105321312956386583581786961628328150459591863581609242573071054524673086989903297085580967170736236219344467936959549900186833486622802733757, + "LambdaN": 12370346251312074332870724462129838692337253107979133338793675324036644874257604454504663401237820223385583141452356406832728377073234711028464532670398839824540412623026144713936102061372029057841401646242576968218551709303391151839209786938331099974753750265683813544176314432947865488644639829079258151356093155973186736378836823892994648654702756095122296444904179894478996022604016938734412666512136740951841349990903322967974684213885102775043333939148811159180560327119677151647322558852078536178214281918350852276078909991498213056983079195158332168527157973870042175902468769131556166850841721990671802262958, + "PhiN": 24740692502624148665741448924259677384674506215958266677587350648073289748515208909009326802475640446771166282904712813665456754146469422056929065340797679649080825246052289427872204122744058115682803292485153936437103418606782303678419573876662199949507500531367627088352628865895730977289279658158516302712186311946373472757673647785989297309405512190244592889808359788957992045208033877468825333024273481903682699981806645935949368427770205550086667878297622318361120654239354303294645117704157072356428563836701704552157819982996426113966158390316664337054315947740084351804937538263112333701683443981343604525916, + "P": 165200398895521785232793120977072857777071962239124079842686368616917226294235774571285458374164442123983736162748139751691380186294989135204501838998801725846011445785066885267463834972903939558213892664931592061551337209188713375629370186611449768973838673413716422330841569115757220837626968544005341181399, + "Q": 149761699536034314746232234401989107195765734248223487467683888366309576027760866648815913767517724744976154294902093433535172328857649910572259722823956540319933674019684132750847433906520775046985871648826295249872452050387931564929144510061789191057426346016935462083565360558089995360876420961273857026443 + }, + "NTildei": 24199931611159732667054901284490432730655788184281673432799593709944600778671364440593923502464750662133283104089850262827029391732187102003108922690506359692667363858878257472490872534272272418259557695490451365566242979496100656724082731811492965573734883806205370491944735968733787315910956955790939556490084165533762006153993369100619396765552088389603636837696742761018700152717925780757548270666166602686810410134455710496216314201100728243709619700979200179375307395338108536012376112172325489862898013926599264560178115009784369239921317480668598756464646766780271050093100639911257785875700458882588757074601, + "H1i": 2068908653463431643806154458199836494675279526119505579449082881064318339507925410665258878193990680580834374535172214976293092618598274161698908097233793492032617772901348137115521118626117971398404886065705663428256281099212947150294401133914965336879981232143825731514235533669488348399079887191364690761078227537881142873162282969110468509667384289619398927299555071835201951023264644366925150859414451218111456692619537757234109465096900027933240786155087591198001276894796561915984092904098062463188145478905052128009943736847997316976312160672286441346086408247715696381189407852858236762374699467116123052327, + "H2i": 20558959829980446976202231116547294366418136649478025735535722578937983335779516069033262893969183870726526076163028164887486281219932832748608769086153336173364540278456142481599658371726284893455190806154272267829477900797754453341403052297963570155859003155230054211243958571590924204763633513571900209861190366240928367228429499548907518719965162692887786229471284227539280348373812393889569464962675302670353560244909328999065595811981269667775787142090179012470330906457454750560182534229196410872086219202048994553726767171353751458704492112821449702111607080379541227334079368156062626171348563056919382991456, + "Alpha": 6068636318208115996729122522066379531202759984313360577568127970474383605397302207042378869313558626773325833282575305200590872373097797664216264327353283900990778547737467664419769013719914237220223361165705830817728955246483878598861065753429326718746278904781494106870070010649161830080016202253750128587485513364993551994547997260809612224637139160358464217226754938125016862778042592155606576425740470291205147734610897437016278706650151722716436878422025549721753112170731931141283828767269351653747840060406967326842737141730563515843023981703230127786921891986332025454077416872744360334736762935983847717275, + "Beta": 3750060602396386393824697879759054275258507317125708254342493351741777400179319079903123788930251738927541271990566462008520369282855502686589669565969642449479252167781427444479384429499855569180925932900131919419730507582705860657733681357982441119692499478575307583826514516615738623202808700120938844677130900282392631668812180966604069646147093547416098214528706324440401928864483960795715288389221789532985052117038731157438141347706245101912661444531663397383665729901522479870257784199405846521570253664338996302873836871117941715270109729800201738990462975260341324743946066257113201700627903502279912716203, + "P": 76393700366050162749373956053312258164376584618272795154338189769192962795021098295179894864816079711762123968857344569689990633157165734183513288567169395573605346909887443769212184857480074412764005027500436205394584198654022100650859433265144371084909451596149491803281197090674495540438670467406842517009, + "Q": 79194787970744552772944875788559481013617629713879624724647179118324187085055559157121044610209366691184710406343411127750302690296611752958159634028378001589791460329229536615833204181700492027215099448133795803572553395382536383051297304355497107393780339516746104919343858629954144229557149068277233915489 + }, + { + "PaillierSK": { + "N": 23565974365787109829436420653002558338612751978005946250683009287762941698824452350842925783048480706135043398451467385607982064790978394019948336958202813310194299645119855728689109592187065223147698672553785671551921160642994009798684441597915227603907697136142125658636613671423255134448634074246978450235494513529373997673587714923952468519390145698734622905672454274921002716637683303931423658281999124167227266760280524431849258878700730972102005699866607355792122606494873247981182878065191212572942618561893778371927720111739404786285309000717762102177293718861398171337471297541852256512378691856093206463497, + "LambdaN": 11782987182893554914718210326501279169306375989002973125341504643881470849412226175421462891524240353067521699225733692803991032395489197009974168479101406655097149822559927864344554796093532611573849336276892835775960580321497004899342220798957613801953848568071062829318306835711627567224317037123489225117593006323173858585499902445969373375128810576898145601370398687975295330215843872524251400278076479855257104692428602429897868444213569031059894357222846724374027993740241597985932221301075902882196301002897156685942740777363224748888153868542604534368744870407110815856899675239897152986570899079020257735298, + "PhiN": 23565974365787109829436420653002558338612751978005946250683009287762941698824452350842925783048480706135043398451467385607982064790978394019948336958202813310194299645119855728689109592187065223147698672553785671551921160642994009798684441597915227603907697136142125658636613671423255134448634074246978450235186012646347717170999804891938746750257621153796291202740797375950590660431687745048502800556152959710514209384857204859795736888427138062119788714445693448748055987480483195971864442602151805764392602005794313371885481554726449497776307737085209068737489740814221631713799350479794305973141798158040515470596, + "P": 139176479153773967279867198040774214842415072965696559232282359608920653244074615431471161007108073339609258225655753834830655859950315592071323750696840555108604453797460479756094948458307887284121925090914428643824297637729858395052855490232506468353296656097911975859819978767863593206153567727472985898803, + "Q": 169324403872506535308042833972947554290109471972635143699374539361491402961920943451449696718738091117103799149767565737222866130323277317910893234724073351935462165216929572253223487004731519524428091465185036356217940919283096893456145773400046565086507321949264563763851968294194357333083325970579705094099 + }, + "NTildei": 27614675962046068547899277024084312796497582685326438131432078731429758369955228736078966232403393128519717932564939784746107420904772358229783701588207059455259502618161910840200562051567770503150540817824559139262802984248403951252387873413977355008106117641673286605673821979334260112540436226212674723934025668596683814586848374953337314261405121168524024601419594482398982286084362672637835235444372112412929968968980942937123148031956496114697316134346209311883711414403323563151755622531177732119691877761184209682988185906330347874368302482624988798895942935852694826557449815813302351003550388152422395085017, + "H1i": 6431113384182909633238735270533890104502722213115053993620977130236829370198551248501569796032069702037202811381051140275065033065400513051513774689573749584921645097186942685963412725381946161800634280975496513452451215386741381110837994921210754530681773217824576676463557023271120110820408519087806691363362502124456847610341997858158147081591503609242798303706865052260389704198732799677985358561044377617144422203650026562164489976317516036783899585326759542741886744454091167808061207911250865609347365318991031342604443846756621429590058302014609495456667443382891915749712336044217554586050990442852295804593, + "H2i": 9647213070899895304545545489314767014326385539720042585866749299185066100845041232180578037555000803485730580204882400541828188021255599686464434290802312599551829888662583531925225213912977594992099462337026103732991329467407924365948381718099943036147485903684049900381042343768982656669090540460581470575846096393641694731328042075493461905912861954032859488992894024381503804893255490170284972318987188654388981150022968037175157751993642854582206140234655035181395286498370831319036079788132394295343602294618507323969083126341855392845028280948796398366359377298333522861850206175833611471600956503614218195409, + "Alpha": 22241874725072667204692308812610289066127299489108269961244733385172133954362394582047488572654516982049712646349030451475355491635223613958898835793391729254706767235372291407458539096414210634128458733088329819167948592333242280199797471868770536045432897968732052504025875758452124502810759206809724222692097998887216383920708912379103403526700989121895379665199990683166435670896003390538420576984131925394325854168091334006802860495596594084498646238223156257756084919786361554629416917243860947711097679782127335085305790720166654130406890091765384889434485133073187759626893494460722797968479090042584612939511, + "Beta": 2571093573260319964714649048387524611171933175868911151722592027341660526306296563709595000094301134850714205958620576084719593795039889963648552892599625997322912204722613038490607036524473050349431661483471123471966877664803062929404341849150582848988179468113055446440122389227987487998539521788115119241298574528052663447677635055916202481598839274936951814648859027398882391086272425313516178786807012857187708625368054262003314723325245144173185168615647892147713761201401294485817993808658962231479200971977355861552300124397090311958201639122765550373801701436375562800536759888557431476959788616303682666088, + "P": 82470010445500897959464090334521974601904959706212652452203284466392773153250967683492652719859926586474817067540407823369013018484665707828142125031280983726336037430339217202598055916406387897372623219372343072662858442847532000095316988645606680093116819203367274418119627955206220421585868556441108875369, + "Q": 83711266110166264264695662311891834136353331163135106345289308691523375137820206487171717221457675649516879479145207925919211996304135116463893031325871139029596072500311474095275353820859225881474943491716615397154183385473230000805324471542526227501721661147329313283989456419289701241864123528324232707601 + }, + { + "PaillierSK": { + "N": 26716139754434734686445314550222096104588936426741666446279727517722487186150141180947581025973383530836171897196819740000573912763711197669349270622014942327309383742222164567992836254714811608807185091126270417165850301861419413952291113602917122135751831812891474124511243941588363744124685283326812180660584964734760100279004701523453395647484987371228083082968965650207856158350772551398991509039737757684558137026129469966648999826859454687361174534479043986714057766937838577726973155857054997303711513490741350262203419689251934447136466306871877327635110735946392336672910150278788619518736410255744590771581, + "LambdaN": 13358069877217367343222657275111048052294468213370833223139863758861243593075070590473790512986691765418085948598409870000286956381855598834674635311007471163654691871111082283996418127357405804403592545563135208582925150930709706976145556801458561067875915906445737062255621970794181872062342641663406090330128907194012920036528480948219870254060808231678904013918646980882470896341617067568075310708123982418955557852563088160249045694909469139607967673622054389100294447134865563911318828315073855492083593807470656005836583256383198178346312414184636242357494515593206391219314919738450266032448570412383726051982, + "PhiN": 26716139754434734686445314550222096104588936426741666446279727517722487186150141180947581025973383530836171897196819740000573912763711197669349270622014942327309383742222164567992836254714811608807185091126270417165850301861419413952291113602917122135751831812891474124511243941588363744124685283326812180660257814388025840073056961896439740508121616463357808027837293961764941792683234135136150621416247964837911115705126176320498091389818938279215935347244108778200588894269731127822637656630147710984167187614941312011673166512766396356692624828369272484714989031186412782438629839476900532064897140824767452103964, + "P": 157195707272547056813706581493309443339890228584643666095586828781267990017180550615740796613460100320350692659541626092504375695690981501768099049823317965475424204815426948736325475935606110722836307881607338411929557840219992019035983701447527189591028428138409178931988270133043653421164422822447560362439, + "Q": 169954639461713149134033045520345696023480679285631389036084859661646375650357865647100091010029692526296328661461667553646532741349534906377140137411617243038044667852680501168010023291301175596708017994192699838600695336265546071407857777055077653329093276621570375302292040668844434032674846608529578305179 + }, + "NTildei": 25021774538223012522514445676343385679567089112924175852741802729662317845407345595213350345211026670762963299346429407733323522004313329678390604020271628665021722065367069445442052310209271941461634265020936168706717993180506881711837131834975647253677465520089205756991301551464651542756334243325974554871331729988771796746576621027568906010908081826216526617323234837670265312100898456757598824766782431090758877304230650745706527284233094405546391502233700138409439418378748521861591678955860446534062398595291070216550722719615021630371874239979280096255720768150429468265061539946484117372598100930165160874917, + "H1i": 21017029508561344855287758341029190972356505192091596104464525030677077303801931282630642391484094030542730819262716457288205985963361725728804473772374771173768364359726726477671814263309301327859982377799785495086239170987842451249057608140290889005645334872188403744397009652449739564008626913361344772445493641587352310719167548565192751088106694816664362425680726252339915551306581077753162281968119820784532266585792633132297450921737017072655901963164136055612085230875298591814978843310694724005768889518296232140065309770721224329875667766485304185522658497683700765160825167265938942702484375373226005145531, + "H2i": 283419044560514051168677259322647436426075939534878796681137153390547382246523209380580875413678639973024300001786543548323220844977925634484802020593285375493289450535253715249901848737368181649186886545408893834906028579238272326203570671063591087224951122161571571035507584265457475853546460220590671831113107402044104975451628146684849151837367126611848483941558876700773147033927247080955619728143849071758393551833585358883155737762341751121782016136304998816315402622218964092427384052183102565718287244785893371242649438930507375843455509001590457571269933116980915588519311647207780721166659659398681121216, + "Alpha": 10515385824214600226543994625916308613193786655673589503623160062388860636537420600948688950731218164781075667978643565597746593864434526341958856020151841313594484391084471516899453088935623006409879417929690776364483773301151841012565272602400359387438984433855873432971794133902116763782105305973445785028101343046990433205481813926089536469560822654609120441715769690382506392324529492166224776460030416766429202818019963785475693973310337383376134236551971626955485155016330992216575869376921360831434947114729277691076387809553682589733668991120649636552796518207529586429359801952551333389938237936363937680598, + "Beta": 1790432759518467322868568935704742787892023347962299745975715473652040365907476705913793192056475402106125126487718842755803946962717218619733772397545419946976675533162766472974791499693553263744108112413534989702056908478070550535783522652837396219644531093685637147416770544193822364496517106504094668092100350533876889396815265988694031386081094727939251566312917745196529335717920734010970837814997995247438943011610658893854265243547344207295475386259915412250635344414089086270818052737575034632357702320349028362518845392994985177207174847551854372687066245239705030771294535933583558958070354852755699660226, + "P": 72424645013342009368773943958641590757133866456836512588001481146899177265482648996553382678650217654541563712666988174700563484739255267289478124487745357807696942810335163113741981913331589928566237884714311824017578067750417050341014658290451398085043602315041015054175026292744579621526318702183964548199, + "Q": 86371754164668399511881152069875381476120759712773506255737328039649708190501526781896075402469154147558113275001868234140009136369538546057866927983356126735893002258434703324124680437992817089373838532376254372436878539739902505868059521195120735705268366579118482187871014338786286933551631276687435903141 + }, + { + "PaillierSK": { + "N": 26480175780836741098634213017014316505678985599165214262517889701665404744394758270507513635914396133610421537581235629409728993204130809255517621297196136782883177781391586370200515968185729901382759706783557295939398740557340175319887451318831468702985013726526461735661462893162026674529091272070296449671369879056988656204820610358858088954426176555164587927821370061772927103171836998738219180837140473551203568890399419564429443581174417945918088028399452027089695030291697860991758311104008921784138478886382992033804078734272418259785924819835419641763748926272189451163604533854609617016249489988733825062321, + "LambdaN": 13240087890418370549317106508507158252839492799582607131258944850832702372197379135253756817957198066805210768790617814704864496602065404627758810648598068391441588890695793185100257984092864950691379853391778647969699370278670087659943725659415734351492506863263230867830731446581013337264545636035148224835522105868755435721876631326787981437504718495998719064460101069278023271857044288398484926115676199045540984825994156818548289957866209303481866572935152828759820559750038229874612370108678062066340875450820059792770213836993112842719938853575912167960758626725863180949073747458504853460007471154943269612666, + "PhiN": 26480175780836741098634213017014316505678985599165214262517889701665404744394758270507513635914396133610421537581235629409728993204130809255517621297196136782883177781391586370200515968185729901382759706783557295939398740557340175319887451318831468702985013726526461735661462893162026674529091272070296449671044211737510871443753262653575962875009436991997438128920202138556046543714088576796969852231352398091081969651988313637096579915732418606963733145870305657519641119500076459749224740217356124132681750901640119585540427673986225685439877707151824335921517253451726361898147494917009706920014942309886539225332, + "P": 156949361724291122562755950818781667331203870994275966491016482405577218543154176616215205289845652191416838969961735950109480337432357603003394327020178628480032530400267466714300014982577463739867530174376468824311163106137371957954406865689950567713291603693977101922878031229154874577706684731367986793547, + "Q": 168717957753493638504591754463344412085535692172873832410151440811303340914594245325034123315942423268704760268449369977223383328009641735950960555508967741090021380391353934528233555904075333911589197810366403623952487954148820616391640246993644738128940069126485987342579007708445035518527862947479299043443 + }, + "NTildei": 24946145482253366961629127833783696869916543512237545299987096143242021925044018830904477554372901545802095393979187133249045868555739086306252491191176652374618251300047864971924418715211188610984990497601617891008052122280076788744763646458197623604695028018234843491914834349428819324970989794879067366958609134958130176385754726128930053497316902908249947352650663174262075540687512544533107969292217398874907429383771027858933746331319748559594012303070911842731317881973964773560451616680656770777983638381791471948574799003221337358663390995601511138122057027678807361319533790264020371204224894186746115824429, + "H1i": 18313249351778079208789660950885159261894973866580713405362813940220466243118811901811685861279993810508654812777696787999601922046678403032681675696967618624361869797788770537775724027091311614490574382486385317208162594806205296293287982058873256388906349156691622673825375111309414215596453649691124921055794691045391988874828536298033755859397558058603908370425969029532638826678238910443739398934495818078931197244988685309755538545356552111669994156293590114370744584107294645216013493424841865362307037198485036007078847139750002724598281625500959430284469683022162583258192402309535332905667308197166568976680, + "H2i": 20711289127977534557365167462937600794186509137735833691344357165272553453510110339718879779055348634590193047617631606153174270486198799517908022189966236411479786716262499949863976892701058674202857626161155735545543131678689545132126284090645416156715963523745543845018026811942460452891715895585081227588334452251934596550500613418578840611074986918722765794738175693893350882053318292450512281994534580010771980369790089232599144326477680091091335854312279735225546276931240549872138775988526872488456550730120129428305208314617101388652426019336246941938980360739672777877003522417183787574542851771582920357024, + "Alpha": 961079079388589809862007761269853332363266206353591939746334822895053766126427672541502762189207308910045149092741385585356850494769572898097713135457897918141045677598773217761276419365496984870923291697421116715438430147386871377856679035318261261166616480519852054063287425963534208026587706252049299221643276903125767227968297399124603566209502106166545562493613584851431267619850752074529280712492010402059665792479579153118712144703558469858884139256148291614702889930819630966785526651856646982171323459338573609352933786329975698309398037270604125007555864760472549734126953175591831820706224954429437950154, + "Beta": 2316604249136996527577473703368480214659443879371823322049522853222552506759674227243476721125762009861163434804851016151875320428861104775802584398339261067689542968138033099195140708096860859619633513551854169412878658089979505072820756636239928334028462268982773296205098298373099269497317084829482908712730596018370047153902015996239432615367885733647161830578924701463953183623495641435648617523348264043432783760277576228570447656564810971816462769629104869045347383402951937749418734349762018922250526697218526592684623053260553279613538446687660358058648847285909319285159815985903636491468959766265877148427, + "P": 75324193684345634701244278008355825113523282334114646755563258496334780504776230411280555393557089469276290533061906733944263084707859347439048257428052431137380897435225807391745035587806743037409406939379739495633972697917804239279547439981500943518749523701126786216693896101493895942765777173914561643891, + "Q": 82795926056616513269710900193924984747193863739768814201499677217197644288508737134572504603736131858772662867055474685371382196637413889488628563450371849810050789758101219893665203995642598953952365243086982331018045873925509537256640891597902556231932587042260275173065485448150054492622639576411700481381 + }, + { + "PaillierSK": { + "N": 25075099918343589388720446791921795059693962609655974799840818974040314485659247956808923259200194571127512186146451622428306265202048418747866575519853869680976179576378155819730004672484810708478499397330279928875213660645501680390637079922651958403980136418641396759552719056879878453564404826773627399847321755318973774099282646090667606179547168048898646838075920761851537517026559746403633231824103698515963657350784363273811623167227499757005831500352795519813474778936522414607131926404404653987865701434837227131548514622117439739571994979398718132745208481689675341848515164923014460924646947481269956961217, + "LambdaN": 12537549959171794694360223395960897529846981304827987399920409487020157242829623978404461629600097285563756093073225811214153132601024209373933287759926934840488089788189077909865002336242405354239249698665139964437606830322750840195318539961325979201990068209320698379776359528439939226782202413386813699923501559297177477651321914641884265478406856080795053590207970099243469502648535121319961914268854833893547553956416636230346931517371160007854562721988234719860846911755394261634257640295303058514672931387364104208174436422890994192523213587028135249843295584859126170021959776184196238081060222986562836547138, + "PhiN": 25075099918343589388720446791921795059693962609655974799840818974040314485659247956808923259200194571127512186146451622428306265202048418747866575519853869680976179576378155819730004672484810708478499397330279928875213660645501680390637079922651958403980136418641396759552719056879878453564404826773627399847003118594354955302643829283768530956813712161590107180415940198486939005297070242639923828537709667787095107912833272460693863034742320015709125443976469439721693823510788523268515280590606117029345862774728208416348872845781988385046427174056270499686591169718252340043919552368392476162120445973125673094276, + "P": 141790080858889163067798565082568699360267645017101950316350289057802605997893843789273930130622161083812777403145225370685716805468546097682715725044081107327541947939681905446477914015746329707396973175882818361505749260474779624280371584390991211161416922944255068030002271928789651820036515627606175073903, + "Q": 176846643759929633571018241816506523373188242291437707343630274306795905731595659974435473155771869645055772034805865442432043327016633643613990331332244972764239007486051985892138731798052207251122865484226200353693892515860671730245196220951456421897200389027167933774593340625832332942489985880538108793039 + }, + "NTildei": 24535812456292946324702596237100823807256064493422101988116258458120645496504642335140356059013560174751878498150389561185940262289574709090944433999230527893816886996941479368193259956866709372069825677723333763182822457624156872771340783421263007220676148123995459118722128873594025276506618641200358423326181723029398005360901627098156138441082786292021032349374293348048281262017724183149152260185497915487474556021539501931226568931286638545478218819693038954021384680226266575540702594205657874951880019414254314089563055861034031606795554325201806169227440122508065705554505477467379241553534852381034044962721, + "H1i": 9288426048707794461832991471309126619837371085840317528274490642829838956756362644425161527484781693089043077479325242048030790121867352384440696525342997668171851653466058283653685494098772044323679802055161952005523208028897059991842494516163026450860817157390516413010355670323645991370950324211502815738151349297759644980827209080529357157400828584270452333885854365795910914790208583722395787883773156330100743777008413969155225883090639356918123719775896835266543163459204541840446613022612443169757648032609061519934759202382518708098786695324409573294243646439334163239202585705098767265043623839912158014052, + "H2i": 19662570636989348670001951096399508149530851507695999743903057533847706010587181050934314645164456353825238435067049867710070341844132470428969707121800541475558410219289868502182563693752013256306162219633617016816145828353004146730516560869106172967795584447375766102055505046120309625953825132276003800616016336324988349651168530353934350055817662869792483934574350881892390687642558978363569063054473859942258732671339651152209984303182673505287398372412083201629609726076351160856215294014522742949190198124251873049921383503222894104415276157401743157380424388208372010114033013253137112331633480745648762645091, + "Alpha": 18648109535677578350174182419734619401758929396681103912588840559248730787014003994374647202628190038912158179605851465903558721263060126706794253423877296941066052784269975766590776054390703308208456088294428785741133602506587760321140671181655771088817387918124600475267863966516896183700662060891927482878916595471574611427497517069605760318606392369072778942900318457633484826829086623494892019150937080515197710368935608763992129782349334067882055847068581487095185418562015298351778389840775252845292857945035589285802368866588348998751332461623617749781107139105475760299897404572613704097739209158827713480324, + "Beta": 660313470667858401148130792675857964921253618850321807994977236964292766625439279276752459632234125485457040486661350400679211411989561436466728935162068131980957884742272358873350733241958636949306123130866015410027335318293098102397639380028418099260847560584713103097107415424842523940174726368096844325376391825321716055304752427284389011591563642866904225517023932134603861026565119856686662541282211618416801713377801196022782690025477613377451768024309623010594293966371591882334022320239282887765556244523989526680927041416152357550940142594452036653590148958802582975476937348110992055727648485335088616926, + "P": 82182898000409505463028997160979384355876510777274705695262586566077063966893756118699037713745114946312412081554552515302159398320983511349645420102336317019644961966656056492907227150080214473079534836276882692105355595029743805899458954921401306950894747500729112506219311728059974814533017587395647607873, + "Q": 74637829321164507758293049323650054827094742446942134495004092634513784777498548138147844639644851367670181453301768762801604446700555351383159800399956666579441644060557665597511213278432575039865883455271985203755655178741105917268103215577596599466456952553120348996788770707651785144726209743368026652421 + }, + { + "PaillierSK": { + "N": 25770141721548730987204072332472144926096055113667827341685255487600901702947504880049680108097201331643041711125686162338242785187029332991152090920383820174742493013796585548588518921268385307606336871626536485520365844518128528597285659731390284511357796019452632613737927642566021402714790786542378784222688111635659880630348633789360694674763494586185752066180783979712939946433415299476593437357192139147559383025427527682085657034900211003693440860669665965157049181378872679388752843559570936546559433824741238728520547746519563812956405501654566042188669270222587904330166581614972631337045680985220935960489, + "LambdaN": 12885070860774365493602036166236072463048027556833913670842627743800450851473752440024840054048600665821520855562843081169121392593514666495576045460191910087371246506898292774294259460634192653803168435813268242760182922259064264298642829865695142255678898009726316306868963821283010701357395393271189392111182632389107956436761554267016461960151784260338240582405761003288594576442288010505693887117954114632649354650953261840908326721532760294459506283391032205861362942232314604381359324906631960491411372813701203026391892707299634136386915126429339305661380128287731625532011525678632978541494449093468355548162, + "PhiN": 25770141721548730987204072332472144926096055113667827341685255487600901702947504880049680108097201331643041711125686162338242785187029332991152090920383820174742493013796585548588518921268385307606336871626536485520365844518128528597285659731390284511357796019452632613737927642566021402714790786542378784222365264778215912873523108534032923920303568520676481164811522006577189152884576021011387774235908229265298709301906523681816653443065520588919012566782064411722725884464629208762718649813263920982822745627402406052783785414599268272773830252858678611322760256575463251064023051357265957082988898186936711096324, + "P": 144471094994361632174761057301514226250544235769718321680792204229757533914901990097221002712695096524308448301478992595057908655807533045142679894818514816891146840581277840914132725981436886674440489478776336130951406107413831913359711567752105686202469123316650656735118350136147193872977556129291841660363, + "Q": 178375762449606124650764198026256528209381829739552579688469768905993259633937288367984660408588813357952225422042011405211094936027157369631748399069086736543176456332965629711901467764870128889296198718562496544785356224506463626822863681043781744663439890330473996531025180121559480381079226668992383203803 + }, + "NTildei": 21087792732704073718006724210354813820723304751895219125666531492964303959373936474557559081219485992141646287695024038689803473518740437409388734708553401337732985860843140604208428126131887372785982762703016190038206052039827825853930550105428659599480000687807532190109363946811212981491367287021202428324352065347861949491560080210713107285487551858856489561616550716983814071569746245998832080798979013745261471824601796729094334337053889530030469994122519634622356364324349906531638640758112393452186484199773400172634812402643891320848471047112277955159917989201672367988365161644298407129209778163987455742629, + "H1i": 16128906224984229277864340521824665825122261942510441702604043745738105868158209157863525680198687056330213281885319592531729130294565833771416178102776871475567704044425045452436041875783355323771886147935262063745834785170226870566517961294730520399402720273694531381754445340691991748873280363396374079652776215831092282131243162290062514492605524521575675847365093962974735791176022529739669256225686526187229198749359980418671994365716472882916903465803922415390675206675773730067934688007124102319261032730070364227242654939133592176629981408805981124145925888660228570020779113119151736604556987192447414658257, + "H2i": 9851977432365942091042223968837199055092785281867774426520485998094195760415225928460219995395472445203821404104058068267237784662212532139124060223115301786957324575763081032486120412296273595775253525452782089630392997146088194631649436052640958432179808023370881579250204827102758604308255506462417015573803343457241802686833763047764425570880288791699910680172809010499338403496957831041673187018687278727590902404276453333395435929791261910522347757670310188653893517032412719849096021581766090837025514505309427642509550661204336541036569971805714032388802497831234946547732870774727031289591894395572489298164, + "Alpha": 1203518491264402840734558039106430565407690917567366792636770926831254210246906151591716016486859448218709439327289721098264159352024397097025580465397903768865093281417842502500472283792152564823540410285428958601675736709207959667149546394765582513400736102269690152431147162293149359230418195220622876645229067380418545557145154128381169741288387488261547742077822837328287293159735625494085227087859698004022865807469054947746791050794871767138504810565107270061528303077334315719030973951809904924744656718548254044432425801637774154631859944033025744390950823538150813566893420163946926942583423586133780782778, + "Beta": 2570501897917963098222991624216628024802927021624180186278805244938245872892665257834801130670699204825799800476403119071749941019871909020966676875902680372816415004696700562845963516277475818229622296600978241797248677804835021733260180960306697729454700300034745059256770711155601830832089036281252093532396305351471942427862002661917713241274115634363357082327034575155954953008778152939116685515196899271336872977459735927647579342010233877723830916280630479313124215507842432273238208625515141719450128260975837611361160794124392658111107010422331101965014616595198391579429618473520627719007638501861928816673, + "P": 75244067993019377687918114238551375866405123366551992169159345775213532181060301364861635029292859934373579206303089426834546525440534498749615700193124878231339197621520488387065345287652616283970339123567268993452693720137103564403239819356233855657991854061045418300078941555718527157616469012379444578531, + "Q": 70064635310056776648957147315110587397816930325413036410655618009578217667968678369374644544166870628384157754658686688480396051466284972191498685947519773949722243058100435014531841539707193571141192706712583641181436161572115192778876806257392176767945252983659910995281822847628603921920914697328426556441 + }, + { + "PaillierSK": { + "N": 27001605117707735462216993559370907025576363079820325318180534690134047782897352986699352155178661349512068835033930599261880443280190992178116301731723948502028475372712570163731312562106700583141099843379771900766027217991711590275583322343639160903052002762497086582998802937120479230388196889652862756088367409807345304782268559374871038784839892529666177613802211615674350199155742148211920522017431935061412098581340939385215543711579288998676243037281576294097510356031983012672482313542381252959808076895266081257506257622285558744999993914283462564285134084787832725820886802101396515425789239835943689077681, + "LambdaN": 13500802558853867731108496779685453512788181539910162659090267345067023891448676493349676077589330674756034417516965299630940221640095496089058150865861974251014237686356285081865656281053350291570549921689885950383013608995855795137791661171819580451526001381248543291499401468560239615194098444826431378044018755737992174269972193304113087650314212963486378523076913685196263707266354910269690711816482210012013600524179081769159735236900122533020341037222440924121251916198201313998812161239233450972181115022868469180830405030304053639183411003684883539512270944203155319320814086598910442953344971220219108837906, + "PhiN": 27001605117707735462216993559370907025576363079820325318180534690134047782897352986699352155178661349512068835033930599261880443280190992178116301731723948502028475372712570163731312562106700583141099843379771900766027217991711590275583322343639160903052002762497086582998802937120479230388196889652862756088037511475984348539944386608226175300628425926972757046153827370392527414532709820539381423632964420024027201048358163538319470473800245066040682074444881848242503832396402627997624322478466901944362230045736938361660810060608107278366822007369767079024541888406310638641628173197820885906689942440438217675812, + "P": 150574808617357497061849280267357369366443753305511076585634002827074150966652306191019260391059416331574908860090629364386681880944753258767406519608369802715614342926967254902937257502824934887177321523348920913285744532851251214162945187554325202889326741956834059834372484690375167537389423883239879517047, + "Q": 179323522743598745262323486377506114845022849387909491062750242454748633656380021481519837993408098705809988672892146482509391356834290673868154443228324643139392180708613129771920733561089416128268525326180221982559703028826200252470226719359370282371265454424688027344886144213200461981709873512265591884823 + }, + "NTildei": 23087700004476980194593337331551070574192919081878401284837775325906253864563721589812066194330730769059846511900766981086736474770582429185966280364685543299856686167693781482952972435165940798741795200022114506322416854426258691362048485182980792902035266506676863050248772433810854473808048204711222901875296171958491837854622944735607685554784396066432419025986579666884675213102118467338971813196059563600225215900590373314389408313817515469986801155609065668403442712907643868020404898730597383554320756396795762757486796954399016934809616146526677948346846759604584844925532714461108890218367538141391264192469, + "H1i": 16136269514060614978769267859514251250048951279831709681250298097805008982743372531252337563872975293717871405098800247867281277199687249261441233707846798068882588387345644502888984237474152281557355311472707527748719783688283477247634461190783027636294862966540221197690082176106342284349823373720174744297429441969744964958072881717587742278590883151152344628056193264753010289089110491192759546471619023441007898783805714870322074011835569184880952034177169212637534104160715805166378240407139319735841047714994046807547528894886945799211743256613675465413798762863143000246699145201977310014561762752607477281554, + "H2i": 1827622695675242162610182631729087432941649762421878138142415662880096901812738722387041761073180357067309277890887033198485675466265058549642923870373160128676955760413154877068192849541865566659080297439182135699059967672359874952927205606420544169388940956689601449871430479301242895226785573382555025437604789704514514472848668574821241506183124453157515268551714969741536515194405243288200831622928730162415557494803772108254606267487094209439289960361115849176589228130298198179490185980246138508219270407438420571345253041428796513393171281287870473322953354603896350788592945088678904131306003831745693677971, + "Alpha": 3998788220896738358620372381513138932777186632254097607339177737953748249403270707590288295918565103340598582662906223266685520450157632181544549199036296130805968751335288267475033324741206968051379087471855305319070735909824628495455165960682163147570069874672464234379210077236349046213070795048602741713187835911608784931380129188785238451230690088192910606334932995666241131336346920845881284361760899335647535829130692419793860442697624258018127895309175103445162966139295512260036677848431782840991497200842608937079687499911636538858971527786411008299813332585806829676969931120248654813299620094566503362362, + "Beta": 250996758783625194064267124703865183134591492027465609244042031535716265438015525005134559699615611032146869196659774747896949926229889496079571170609780764690245179864576633929029185598455049582040797499664423574253463572414697446227325363661747679251040272100549488004871819622924057186323605152821731319084814796712192269718385693575959927563627038209191566340672944691845078917935403606837183002474343213119002967121227198464815596936467201619237200195575066250499366755102298110167500346781824144597237041338350258216905185956781427287788337788099939043555602380010728658688470164258144580375863132347789394978, + "P": 75127965180017090666191907716426180868664944876977503041336542588282220859361186303808592932889526678157682448233468221756611925720006810388196319236449928564533883617130006186048097188907843497276961580607071082737570000485242387896789076167088705347126845161336681262678168960801100130160322736069822130633, + "Q": 76827916040171021817911451883754419462693217589853941397563086160749794035376117291058168896508217303356287531468585822264013662948466773200907112500307922186772309393298017597919199235344365061671378668427029095975950696621090478709400973347801044583357823319426409685679311442662621225640501227800523025403 + }, + { + "PaillierSK": { + "N": 23302748979887206813365731351162912918078218708231509967701919527004512901509418034441762936203655867657678871457954791416917680827329066690074370257572609090915311153595029259411285894846505379795773226776256871579581999319479109694789660915123282188212238719022587110461022936757831539305397692283093296747369436537153830007902282331134364284061781999198955778594100046582905092797254296389593029690454181728270437725637201262199932316730084187133202570465337074703268041445783132858602578455191254459764215641302995671008623881772916648048941023215159640248339117758638356920016718043721823408378778661681019354217, + "LambdaN": 11651374489943603406682865675581456459039109354115754983850959763502256450754709017220881468101827933828839435728977395708458840413664533345037185128786304545457655576797514629705642947423252689897886613388128435789790999659739554847394830457561641094106119359511293555230511468378915769652698846141546648373531437145844317301740591931464086601590495757815050243042225782768877084874674816664326471042984167685539948168902732204793561918865378991947268409328178149476598820581657416592576457750856133922159825577028812535720508887506016898538517890857583680650139337349584017746048934106729136001358223028209623910818, + "PhiN": 23302748979887206813365731351162912918078218708231509967701919527004512901509418034441762936203655867657678871457954791416917680827329066690074370257572609090915311153595029259411285894846505379795773226776256871579581999319479109694789660915123282188212238719022587110461022936757831539305397692283093296747062874291688634603481183862928173203180991515630100486084451565537754169749349633328652942085968335371079896337805464409587123837730757983894536818656356298953197641163314833185152915501712267844319651154057625071441017775012033797077035781715167361300278674699168035492097868213458272002716446056419247821636, + "P": 167150282991188460243992336346823320434142052388807860214003444237170760177011239834463480709396960304114312124085816470278462797900499784189640703034874195776965180148046598774162413046096693197642092184449002375311848202575004970186086315741642899526747242678148146765240481014772120702220212479222460927699, + "Q": 139411962474006944177106131859367760446648431180047432295645036807980162870893423226476606895088886053076229263745920382334345681098826419049025048774106579973105220134421700899287249907382293417802472302796368224255757904185877880785818925758349379421313200381322174662678368815491430703442120126039310604883 + }, + "NTildei": 19903824498400778851539192064240880051125977150814422002819338080252032552095576738670094466463234351366144635642956346960430634075253161798341959968009974054626120451751709629573534244616824067099268567062571869474777322407168004614081811456584186554606069439525567877690139530170193564196493186500878460828966194817896003097269442804887727350771322057177623030916946105994388537646518927100070455838435513635931070862635042177166181733891796052673774821665346663954542228261906537986416580313872004251981618907318590719481316442359578256269250767096471090458917992068625446890621598997894739511721599469987978842949, + "H1i": 16210240195359464220736208060859552394703635249780734119437028965346995248632758947140031346216146993578838134862406539974071858712982270604648417602030860502774053557520665667971784651045945766506793729645550541992861062984414041213059243789549996102670362343876282150654554089552503229331397100082376742115576242890140722949904811119824177878945928999169935840773167334579129167986206146762169755091976520455220465533820737963402447943074477158616410101430438135613565694882527719502452921018455396963242416803376356784846522765255139271624936173681497741823665576798047672260756732149506116596135955976990242902249, + "H2i": 11490479228153319532490367867229533868860039152882215741956053920978626691564585697158106531643475341480820145448764282492736413063670356141897376973904609541278168093093562371473412601770951615614535703285537080538209499063546774080654638042226143809049650054225798241490569528106269635680890524773534482710145135734946969316160364398209241914187382919532283051121562366845718296116897858693147713418738010320828917965476103046079393534681564133831281244993569379787069132223514960546859083740848140079436441768649996477325234941941915443606176808143368885927552040214628536712555418240742909347260309875077601387259, + "Alpha": 5879209502884269498045319279712743730559906358301840652856626227725072312318322201190782652046954734338779534829657300241715964814946216826128495592858593795682396839641277114984356166670828933698661215824330935103998236819819364951941019361861463106078048184376446816638367050859048983216896968759159006637362229996397651301135227020682204217565882694664934393081578893273847739743245730652372982826991300296533647131514741555913567812853020532910095416201070903739296586771790349813528542823664046304447588817625337778697385415615429009875272168488461136666101296961509160461528395277214983308981342314886274118564, + "Beta": 685240498001608801876806028501058123622983333333162845238497971443529520217656624227837531637712280451259649459615358216398342589720870194194729880825219753600062656794320602053677315586086346220475820593475790673569020593775295855028383505035283315115784561434855091375057386939385889818725393315534300057405474134093777992596859936229210407672133228610440032065349267031860636197516836734223307651728951543663980168722009896850663194924490476929467316004178323568831760431796349020084008923160245402936123602667561658531707317892817235015171559468213708255549546122014699458752402161568234238705365655734475844686, + "P": 69951340621069159915320409281784539553456618637907941081852230758548355491395040153069042271991504054875349534922597982645970746573882088918721781431143135816276049126870540936313993893342801526080282126913073141551629991424738821386691505394730299531185305674469757953204628352424813892549469267988658427951, + "Q": 71134535527421325908877821670601729543553260769452854191374782534987535105477895388666613531670721568770519152412295958823866710209474118755238633567448636545889743829805458692554578918562350048148771530912772455363523533379964966813447756185606260667244614532586065634787881054949624492169497521341025650541 + }, + { + "PaillierSK": { + "N": 23124728092584617790121604442860268177487181376735771856832697474629023750061210659796104520597193540358156912695302521537178983181582449690887971349386553742250848596178606527833810366070697972927174043733755760161987236421092896678884390670561872514685664217492621048491488512939872835390673528163085538866780977731969099001658629812581821938996949644303101755809782579131213540585998876139847588301300713061489559026530418688406515859577292946628969455991239147532746970125077435415587161829730798195401076950329277587053666289973088452447476542447387849446366639361621705468087768219623147539957442808115364431717, + "LambdaN": 11562364046292308895060802221430134088743590688367885928416348737314511875030605329898052260298596770179078456347651260768589491590791224845443985674693276871125424298089303263916905183035348986463587021866877880080993618210546448339442195335280936257342832108746310524245744256469936417695336764081542769433238252005615907516659047998482755734684059255156104318215080015600655651857544827129063866962989317113550688513939963900017750743181018029235292981849306417632685118298360006664734667561934921211675874836045823780783245893329033584148469517862132590807008025614163037209353173656507519441024616692306571241958, + "PhiN": 23124728092584617790121604442860268177487181376735771856832697474629023750061210659796104520597193540358156912695302521537178983181582449690887971349386553742250848596178606527833810366070697972927174043733755760161987236421092896678884390670561872514685664217492621048491488512939872835390673528163085538866476504011231815033318095996965511469368118510312208636430160031201311303715089654258127733925978634227101377027879927800035501486362036058470585963698612835265370236596720013329469335123869842423351749672091647561566491786658067168296939035724265181614016051228326074418706347313015038882049233384613142483916, + "P": 145072115968680558171763362069417611993317938897136182432737887294183187416692437120491541095926011380649657126279003368433084813496984100828029813324810224937349759287156901698744933664596864360220268022692883268920752024597884476154169020819484510064937280435952404434459033307460983317033465787979181093979, + "Q": 159401604768603410168770453546892857635513195093756936946884660635719049454216784761228313279396067453738524872371487519937929559718272787330353678967816087330026974241200520387372893041264091411829059255544746756566422478717136807996368485903638157767413307697343226614922387599147125340874743635523040853823 + }, + "NTildei": 27767802923717327700184269138532963037000828345587031451741370638401904245811467828858947295806705170321879587520870252565052935695841394474668673571318535495639548868576436364881896119906811818484221133493803456544137445050294108707213301004737728628866611862691363782045722291491675287529391532003459887610123502642073557608292767482402372967718542044402487221809632109532072099793565020849020685032641391246435999228730927459711490307799651005139311697443784925807409328249673139849081441653744391330583151314184372350756558462910039857738191596424232144570587706501639343147751866657136058766945288671367631689417, + "H1i": 6208381716067437983082687109340999526358477219345070115122392188036741894024214867820037124811802866421821984084290838636684573357267270822971128179172208160602267884588902547294910143441755946182999848736603388785467206252175526988860182601184560502932212557156798253830294407584919872546797992570703023969731244686589840987317034720222055961234056046060171483958189622900785088988659511858296810721482323560487984645061273163062012197153773217857102268749281916186979223468612068011952281215521062423435673222341148235917175848627461899108419067436479445044042502639560730045763183702428671798382876723344099963488, + "H2i": 18796476414135709751629048220715294184560704926876063105990029012678981947733068769045257912821160066325546944425876736608540453951014807788517333662608533716273590847347102498348272768441020137027001120357428908714335385665967132589229083845037480940180419673346682545813753758298526859195587641960786610315970846349660333678173933374389394401377115661401125802471702091547415760954354085573896086645062863029149606683838124507222192599748629655825843833502804567843246099029366889207065888345456920443290406375434223893651807850111369354188482610139515167854851061853064300377539272100968902281453695741535079260705, + "Alpha": 9862700642623631148310976264259502526914187788521108628675810653956106435259280551861309918244477573096949769908609453106572399587194024681608864346104731264720235597305314894424146540814128552826679765691624032479334092398807060533990519845701717646427658839584306284680858172663601801069911828352426838443793761022581419009144730125720687976221462558568234184549197516663079816124646705535148571636768591710628672994676656796637077518210918552617778258933433198813738517805953825773599840025343930055907229547683991363681805339706963660208947917815529788885279367607454551566134971929618646249875894249498158464110, + "Beta": 5685580785459934937149528045040854124767855506473361517935663923560792294307722240384736584681584148054335908950830275936922717097566730668129247672283609808651673508408916023531905023516358773886842810651655660037640403535756932134496419756131785430309483334764202455710992779753423408492884425029198611740052065669224186299389931100174093105748833425118910142669678513949110549704177482710509852105179349427377701880481384953276276216972337117914903504441874764118882674934311630870827638737385873815543635693644717863236038196312351835010801106481907185901337076317183004839106845525118767629488003771163019797802, + "P": 85368886831915457326952738244363437873889991593735428842566935405613101343201417161963510335455485461796857264775721174749408091852794494398126735429857321837415130747500861474105659265252370681473522080958782156081121036459508309187566197815676663238876050903068457291642922033934319146106729648952759575989, + "Q": 81317104961172567752241410225315381929460448532419572607679909507645307065157191121732295237305580335176472579623965789229092481601481653704436615393896437994065326288776098958292227762667069779072981634859323533854176089663269284422258255279065191076395996634296368858788165789071278866810587982959020762061 + }, + { + "PaillierSK": { + "N": 27547322071909745226650309844863580276991780675170103574682338171064554604139886362327850194931606500551777777039349254734274545608516089761691108579032875094808604290719428391317659108939762019048280285594339232986577712565763472341180029709644955519227723965579057298824359119160814187688347791126619281633462407848857075445720338668175910651772227997900780891124462745008507746588424644183842466487821041018775945944797765766554126141569069523989269560066832815519819557166474601844743786185799138915704819495432193469524879509348798545868983527569708828321201403391520141108723357504328824567478692437101383499869, + "LambdaN": 13773661035954872613325154922431790138495890337585051787341169085532277302069943181163925097465803250275888888519674627367137272804258044880845554289516437547404302145359714195658829554469881009524140142797169616493288856282881736170590014854822477759613861982789528649412179559580407093844173895563309640816564859480516299954336509611163622690647718989065374360203962457181595964521738734543075295459683698834846826568820459463664105741675182238752991912344042325185476328946488287119695628299432287243767324177575206009952052547366279530483221468884848986095261324020979886441192846845559950921432240616051725033822, + "PhiN": 27547322071909745226650309844863580276991780675170103574682338171064554604139886362327850194931606500551777777039349254734274545608516089761691108579032875094808604290719428391317659108939762019048280285594339232986577712565763472341180029709644955519227723965579057298824359119160814187688347791126619281633129718961032599908673019222327245381295437978130748720407924914363191929043477469086150590919367397669693653137640918927328211483350364477505983824688084650370952657892976574239391256598864574487534648355150412019904105094732559060966442937769697972190522648041959772882385693691119901842864481232103450067644, + "P": 155247059149967354084839294154974543268188254067406366990896286909265502524908949894228252565424734245686174427630700998376591941414806462284396533280399690125804818642035459314482960193990334860865888879440243912359130620742981164556752648332862785498241888203157196500313468650313765588457688438055884198783, + "Q": 177441828674508182962480151693690727208601765702625803725641543736050315020038225203463623003028909103396118379526145840849322716803898584198889202098348475023062080631462568290869569392944229567304282260841537537261643793873258320345787941467148070632436867146403171726024195162895157136156522766942049233443 + }, + "NTildei": 20567074324437004860130961362455025001909801265057178277020087393519916717412950352609431761865185859444779069157443849864051311360855368431238958571177631812653390619282090811098545486627342419303501136755766301034337539118654852778850589405021484139303659750102568696347460295364004011305370787110603469584814549804891518153837066007989945196983414460543106508232589115362933743236629226855288448484395490000780315183835206216531923241370472380752681979742164221198631667219483711699365502635292914877471641645307303031182806223438852500586595433289102954678132364400189788094218342863948952633399455173160198205529, + "H1i": 11583937985507907402892469337634682138766442668881603401866296480365817654208158035911511320132440739369803415367866567622948220064469406785012517544558957767445426275535423663292998900767299085841712066288729178546894279782305926186316125480846193970460014196153742227701018039359932668176524953645003041222761743869767326037957756935910555679472318282383526777449054791316630153461774293621538528106032537470833276118145168677771064665635416097825927883662685229479726580698708577302754754228420496226830187101045964370498715084528292997565523672024323589901791233177218817531702157977515762727676913406391967730951, + "H2i": 4103108526771659926799412070316073724301935320970399212009404888105724812032316256810422705740538600750787752269648061235730430523425793564219922670582462890996160966165633967624994745102316991878457118955665779413462047348974918210666076430008190096910716543865799968546401606093461922063239372076665397726829516108280179009214157980215334799630326163831517853913997541922825513815597958986066300242538358969504993161757325541269519466429783979645822473919517013412314958724001270326219273916439899104467499554711956713891985428773178929660837361857836520617707180174249710162426509665454502015646297117306209530301, + "Alpha": 18055437364515175546735308246436797761201842673094235224735684912300489362965085430955620981078682777389065402599916356464665737240020019911868408275026701341087056490132879002503398931405000817273079457937887605102647641488524890145887586935724681924232727531730511918417230483387660971613708327555587789450502086998436873312567581023888385507738546029672615164687784219579882220143865144440576643943014488912115831127801664928623116931831195867016769776251253742876928822432599682170048710035015887029672180422769191678977752963772904424041789987559418064416702803016211721433235449074143715677399479176880205416444, + "Beta": 2772655598368718945257192157427768052250780519629826196765492520598718221090913380618969152883216174813911738817960322394118610835807090999668319079610470241765049954161544518526650632982265033057808714290159961358801421246773369513512359460990518513582333036492658454335444309323156928537200048841095506763788780988361745373366063384026051446286586601801109452617921463834635272630637868632703464797985934483698374446598576959804826672649410149664315042409247877229290214411896483796854398981954981320619327877680605248553246514091470180811294848573680716971010864761624920549286019963051725408232709000877717303644, + "P": 75298143985762846165037657380932744959855561251302643860714794109876663111265840206141256776373881260388397354971075422494798460027647687404386066916049406413408231286970203311720727797696206115831674439849944837917068773998576340643404812891471699838271803534963296971470882283184232390104271224150911196651, + "Q": 68285462415666471780979397868570186453961206460774304386236484847082141436311645527059130149975344939079236989827241819939080116830315982532162931314204748201817774533137662071484068556666756023184221397688806960841341953417914010402707457779040071947157937215009274922703062286681954021319811102383915407271 + }, + { + "PaillierSK": { + "N": 24103781230937688737884236130945722667654341902440585411476249488195016405492909386069353042333922275101269190084447580578929222037194412822630970754013071228553282337978349864037469501340871443177555389195459432230670167054009955607232453312569884988938406206833104148948926507708785190117181086158367305176526265966086673637647095369991835452319651807022572945778258214239450350661684406662412340516892845427333315594947286468457091234678752016297400772726215733132323022804166158220697637564174360975093981141425619287101576809838796365346438937225097940063116029082221237617418316802497826387413669265630920080209, + "LambdaN": 12051890615468844368942118065472861333827170951220292705738124744097508202746454693034676521166961137550634595042223790289464611018597206411315485377006535614276641168989174932018734750670435721588777694597729716115335083527004977803616226656284942494469203103416552074474463253854392595058590543079183652588107083073298124709370530845218278825091420534120856769378768932203459698177561726457311964604512477670028969418042169533181877968221625812486567943240569268526685113955494069097229786530207197015262134375231106785205316549455073947173495267063439816560966126261857809093038158174708352487891564657781573531802, + "PhiN": 24103781230937688737884236130945722667654341902440585411476249488195016405492909386069353042333922275101269190084447580578929222037194412822630970754013071228553282337978349864037469501340871443177555389195459432230670167054009955607232453312569884988938406206833104148948926507708785190117181086158367305176214166146596249418741061690436557650182841068241713538757537864406919396355123452914623929209024955340057938836084339066363755936443251624973135886481138537053370227910988138194459573060414394030524268750462213570410633098910147894346990534126879633121932252523715618186076316349416704975783129315563147063604, + "P": 140308464431926656593012176409457482947869022025044684032530139849971627864682796472681789840207403625152979236185419392373638893837288588638764753330352370876735088902595087810728472587304390665764115954333942362803734310559247226715494482733929808125229193053504973159820899463809639087141607227119446361443, + "Q": 171791355058497562313021503145820319188941716755814722988190209982559326441878157275106621467660486462122397522677528009719696404398211802685500132914724825202217705990582932215509591916455576278805596436629463353887209400369401244283953920364288498815954583505000646271521100989271482324488932722948326655163 + }, + "NTildei": 24288448491457965206990464943919365037891083187797599814249067434936309576072677925259783415134392502630597159680261044890110355160564655836832395638648567544850049873670853548150697331193524777825266753504024003793253898562258005352624897031991872613724029792013508049844984340291599509724787236007183072607853862627331249227722131583303105067341610475925175434689353247353950179886259390133691897703962514020051150818643683275771705524111339349728939288550254881894334976215631656185980986989238499248437767085106760150253618580278039528162824338616296411685100357014410757503432986155457730355208033364476869644493, + "H1i": 957786091298976028077804235644486007933462014905520880040265088967292685211279414871325392672320002515813794613355587805889312634310947532071226984442129685152628823287837876950526261674705664243023863486158999265912536434988129244587909941065251874659450834582348641176745789072031144910187891009735715190223419284573030091577666020611132437633691868484977170162279638064505362069328763310200720049859068537210043555095861870246473610491954313491026927825061484122803595708428196155322226492131178293790130398330324163157985821036413936034329740007520623768756885997908920433123020266994290134410672777249016752369, + "H2i": 8821038167954332305130754785293438747162061831445869174285394507956323161539634795477840816358431960915540131268138910915675491055992204656453548755955679303111511655317778388918112371744304572461635644513607969229018910417312874679004326442428895129449919627950150478386615302708088738496044532497744942606816497170141698432728541888062595315780624738836763046789853260434966348246080815985980304013575700099926129475954590846922803133473008416045379933285925713792486791237011295134428613318953103040453732347030522139115493440127901885377506401400278502690603713692812941555317829388020722764294494238417099513557, + "Alpha": 7384027124070014341101948839441511698417044581242861991661911097046626828647314494774292009608356406348747651061963585549272097411398123454750886546164986217376126207248551127598909403088859146917353956332843775689072148780409938098203038704410020111125255463320227514854751896616731569119340940609064470157563266713737280512373053429526177246423469227690303568251312746657784530274546335984477375249876216549308807957148433444302226805629716633239839357181979109527598599647998793967877588515049689220894224970416926264151020952874624848954036373933594218893424950824180342787722879752611582593681240111608058777903, + "Beta": 5912084018359510709356677407334179928567353126943715003223522980161918149108862835324275883851161020416014928208122694804092438135580555218221223308533174494323931684004085672488834968500987861876531658848639755856548972796912793409993982051880144037984761217459770404927756388130898577290699365217345539670430881077198890539916910465762952624507411618999551557986028664524654369477172162757661303398250044384149603399400265780419744698932483948434277995525090811403764322257223748586988349733939996894379387987741049616687389241643495685569632841355979892564378027726072130411258536366621247189257715908969376565834, + "P": 81769035332947401449208759536750334338900412549097201138617797420117337426242067831837030275979616570542730151191633442062196563219773389081039945414950471598799022193898941063129977624205087250340933603575322353872028272939971196404653619547468358082113750855146736604189880912918933878435884994990662066329, + "Q": 74259309751424204609960712451952362703454358600146837379708453661801382892660019133746222670307963429683628304340385171071616288621342407452791467374581752902848020886482016913344170395857309852229634729805310790486895517496875679996171089503420508911677388035794864212514555356121862839607423934573406417663 + }, + { + "PaillierSK": { + "N": 25713100084555019186961207379803457557823287383617068489774086177746783352837200690957893475687873984699224135503079885859887330457073155292498766337859368841618317523562479304097623229264124925121222350263799279092391127317650114668314418083255025755397404834246040329761302545423982491107419289988776676242711481501195450747814120980793077246355324698965530121985929738120743031037749774503824187706613598697193100009075679359902040109684669918877841449997892363025814859213733013948873729282407416646221698942241043463620376663434334785196774278838307115297943991194526358984476956237656984616706807496526239866101, + "LambdaN": 12856550042277509593480603689901728778911643691808534244887043088873391676418600345478946737843936992349612067751539942929943665228536577646249383168929684420809158761781239652048811614632062462560611175131899639546195563658825057334157209041627512877698702417123020164880651272711991245553709644994388338121194883321081404670174523500813591235140799604500540356269071443562678703054505969927425681848442886646593055307937413559211302775161092192486848597122014341660916919405151420524405414878100344135898733440140494732023328263853682115496012445897904835156517551631482972318341692371364021045769746409842558746102, + "PhiN": 25713100084555019186961207379803457557823287383617068489774086177746783352837200690957893475687873984699224135503079885859887330457073155292498766337859368841618317523562479304097623229264124925121222350263799279092391127317650114668314418083255025755397404834246040329761302545423982491107419289988776676242389766642162809340349047001627182470281599209001080712538142887125357406109011939854851363696885773293186110615874827118422605550322184384973697194244028683321833838810302841048810829756200688271797466880280989464046656527707364230992024891795809670313035103262965944636683384742728042091539492819685117492204, + "P": 173585844423254872469878612945894611309103160062404554733992686689875324519075803735303303551910879009482014213866385425396919032933652749601876657724428727530475291242884023734872474298608503676478055323839754365994612117915051930940198646309666796191027996424555706520926322012015729782143552829896357762699, + "Q": 148129014609386534995195366220000164764622329902044854713794164305510300409662030913669520457816946394524975179334466816082515526428832784302267598029434952173505729160546149165190425227598224697946176738120299633579108017811918623264550740732830648793880891507004707826867249482913212743023761846944764611199 + }, + "NTildei": 18503977412452181288073242460811243213376077853729950225202078320494553049290179013708649008823287556020955748430422539205101454251384321927100247074445251635103379803795875598911630900120589337496959149432841285175390499615232509118126550762662454480747066127548876669287808868311464601892765502424878976901397702651378662653021600945177785699582814686276879452142304072401352702375299376430930412490243188414697821736314038664512649070958312437445559357392236568057134669442203222315040839216065278831401669429959822887925603904283623751009524862935377231408770988519567312428892318661670403187049495910824974948929, + "H1i": 18104965721049179280288122700143544153070755921794704362590670409989349804891059609936558905691202331904499802966558494745323793288097835436183756246448746627902547904115486352250258244281196876394853893776857137018194059974797804055262010391211985590148504455924010399666302626709623950032452748384876940838390795560289696050506116610301931645230416771055788243999792576224071913778500574673061936464838986790630543120809268517740074059681997040579116886474357597756476114239976319225139867893535357143110808744290368650942477232389147786699789510235788562363932509957171356665127971055492639442789355585479166090326, + "H2i": 18145368699322232855243127293049743646342954798101629115209422121099568723582205053558925059910085027277461466382493319123912771865099852703558443226068619303433893340375991928793769781936385296568364271641759541819309513704901082831259049219555296904980176002465124309501524202392705072224493642132628335436968986776074159139172789688096878182777583542700235901210492179801650631202723385813705535383967503942526895116862220357448989517209183485318360211453544013007300884973873302684595598671220825289508572401089292777352377040733217072129880644469671286938461408133582489038970925680261165805079379324273591721888, + "Alpha": 179846736986286230936617653128884727295255396728854729147883713979820710188928769724170047474486669500106134114509633369505194217535368455947515422309142957272435748221543770308051896686902686357200490476065566051119661923561514592518751946983488195069892085891681153301555081539052508105215500355749034400136557154826530861240266806444413691292675102415787859183870770126693472005332526974890088092046194923654362756298013599846573973639371849713859506709732811363062702633507706484454713586780015325219052187141386233954297976235342752988044388080470280086582502393281251449844036682512369142261390721589358711642, + "Beta": 415134397096713815141018927159697539238774986481589181784421984101433878266741695241639652786923111316278392328078162332302152970508790047430193292327314939243764163830062496063377234147980323751923104503507521807086448322695609725707691653569440879371962748505399859558391866839899340029581760987539577892789271188118998984253780732849250784805833630399555869444873071975038262848117408625356011926934043926522781675609934011056594698123912427732246440047096952429939923178029953200608318203254395396060341814566728320694910411847390542357737683069349807204559854283528740649329268511076193840373378029994320819046, + "P": 68502269340979810333272052958449723975867312387534134399797357476457424848722376815064554055246908247301595895664271296719056311071252223368506822781639349890374887354824452013415162820925374445574742214093850406579740533860368144709116245889215599432574954146813436849127351532923855592330624111667699526311, + "Q": 67530527055775320593163782756048012055064123438619719483950214042603939079132076641546946454003898639241390511253628577898617196693931379825962086388093435563098040110169919315889455977481008103227778321056708046349945465458170848550733936378283705322103654547757107099525014332946047086109440338033396509111 + }, + { + "PaillierSK": { + "N": 25331290609620858781627768321101762479680422628077929914136054613173362271386142484432664786153964603134980470441960571048173422036124808722244199535267868957372002443797164945349546886811507886045977304418286324287442184106692457031823387024228719368116898039688984581799796187501275899708963568778246534620303842265950507963362795621366137670785492926628878447365765992125032867254799015999838587676957200726304764284062325429061034486934819353160807079237299562607542264930897851334802122859602074584459343268108669360996373790233279452783732456576507146014131895702003430497980987901457954380164492073777895589849, + "LambdaN": 12665645304810429390813884160550881239840211314038964957068027306586681135693071242216332393076982301567490235220980285524086711018062404361122099767633934478686001221898582472674773443405753943022988652209143162143721092053346228515911693512114359684058449019844492290899898093750637949854481784389123267309992290825158755030957664969997297170717939877982153739794176531903357644960374815408366586905003702562398479755574277236702533333731193603992651839302931831643053239347704030492051829306431602353199615731253399824122590013505300823928928599946157475659296427559722666669560568982609287462215061772864020247282, + "PhiN": 25331290609620858781627768321101762479680422628077929914136054613173362271386142484432664786153964603134980470441960571048173422036124808722244199535267868957372002443797164945349546886811507886045977304418286324287442184106692457031823387024228719368116898039688984581799796187501275899708963568778246534619984581650317510061915329939994594341435879755964307479588353063806715289920749630816733173810007405124796959511148554473405066667462387207985303678605863663286106478695408060984103658612863204706399231462506799648245180027010601647857857199892314951318592855119445333339121137965218574924430123545728040494564, + "P": 147360647512751857031032212697859360998519371959957671552109090541596028477479885130931068602612231427663167520443141760816601675457505560994501366346860490360662959826111466904379580656886889146416238690924099740976325164035162114996724045871119896963744204052858880062883816581187294294892944464178063454803, + "Q": 171899968120246044416433468673683968351093798704613296225303837776721548856569500052174345264337564173844637252470629194839366144014926584181002034284575408960772826409378323446318883589851980731643873114677769971774868599187515689929151210813072297731794836529699217095976033355052085160841424063871791640483 + }, + "NTildei": 24112837805420410269937874649215787566974706819473850269770008696312798370921039813993547872748358857225639207511733334962417918438202587394605109600668962297905687102143632882982749367161775481012077420107246472888759248878092007054597903076768372528562932347564890806070386889311658522968515061751829638281205651237817732566654887597490823811440962271191055315627780550583579779341570445835710795950991519695983013827617117446484613849263657270512282847776733170854272029903945248881697649256425406788858468856829425269906268378718723439605220415869784395753169103186697223989122654974453901938811766326514829582869, + "H1i": 9114536768171314943127902174905483174802789082458326225800751755010439291551772668673891657068988460193051936505447525873827207185455023845277018524340706207936391189458211621151662519068973150266449493777903840534008178949516831151524415033513463229963215995063486336638565790221605159041350099412746604580621189027120026539182252734191489139683984104975855344374712028152568013066983232100028556037912891865190997715890046875744406332243051840011917170013865696001493445845157377781388705558203113435380723502098658401992145211502809169183586729958645510555244273952914456153502304345673662377876074992337459566114, + "H2i": 15536466835338686821016677991201668754319642993180819342382288869303283571178288331388367609397709207573186107647457240018884500202898281476869624460919579294942407574534010747660325314985634971090201157322345476984361532101659523435800355798349317657231607644732814373279756461899115733473521363598507893318375103648696516825983893921288043426638963402743736072100780330325750994093809321004688078918984342141477450217705942962331791364485194074168729463922407310202459989313505224113884028158905175554228687612463169864924540087277525597830063907978148404831396872579333074499209701135879989398065563889374198252869, + "Alpha": 3803161135753094499217471857050592767584489532339949491444265341893327314347074578569501008364261211617158864198796140080967191159612655184818331908391873122070997940573035111778586014048768231712024836937410465384491301012673388187582924393420844314088377872556195218989200420555802626039304138700883969075249236068418562247922187869802682786733860890563284078345682719032199538080579199424515521479918799247394457682065610602699520931816650494300131929393665936036556777737190671262001825501699643387512762107384487778127343012310084003631000037620283004447666841645613630260140020086074690346239205867833117312837, + "Beta": 5790614717799194432475129005694587505817515496912952554142215012702567825548481362678481215281538470440320688275517813253054301371164738580564321527154749461439924353806046975805795782862713733642990935350336406187537721498007116605658843419132846381173995019123894770025202558221598077188786184920767802262964315313111540214769217917315744908089532079314928666831434913540666448207417313303261294271709423097074769299087081895239246301356614668132179181572655746899872630493158248031862343410545315692437615250708301000263669506283709633009279539114546335072073462681873207002828376706376763931736004831536507223066, + "P": 68133154163261823363102444224314302732520817233429954595471568756264821821004204430614104107043550127759504997968281968857609855349323479915893233152048377998917196615852691903546552308884773489491787098524890364566914957248418475541527965832446603848137359278758725670604047692115926643874441904273481382471, + "Q": 88476888020040940770767045952337328214054897423499934078088811750900664961200195919371508388892001690427223612816996932381452638221636060121696718472873432335074256006234263561940972314578820631007762954198298947745962052414360554732501957732790697362591125271943146286377432362645620756661954455624750464141 + }, + { + "PaillierSK": { + "N": 26923456472794294953433008015984992847243115006033876516710179863104387709100553561351556056172411814593503040527301921908440213314289978782365319581228838299964316686262562979742613566754388961754952457812821433231323130473429641175499810283265566892936298813479754100142748143920576899391081924078338066625269257115097007765409384961120705545088069456449921235662841702270921592461973212110828014720649659279131728220016805657255113680826683102125170473411486802021390279159708018965349847151453118311825620514940472627430937881414970959128436760385325923743847688719699557318786706285584056802072689552593014062341, + "LambdaN": 13461728236397147476716504007992496423621557503016938258355089931552193854550276780675778028086205907296751520263650960954220106657144989391182659790614419149982158343131281489871306783377194480877476228906410716615661565236714820587749905141632783446468149406739877050071374071960288449695540962039169033312469871845980287471756800514475495473172939763845521381577942233313347170456070709055645292238632353737171389180780411839614179624672187582789890108426115940996530884530223805192696058512747677873899010384144161947598479661990783033241775145763597372698115544404957570915720222365636925491510769345010826451286, + "PhiN": 26923456472794294953433008015984992847243115006033876516710179863104387709100553561351556056172411814593503040527301921908440213314289978782365319581228838299964316686262562979742613566754388961754952457812821433231323130473429641175499810283265566892936298813479754100142748143920576899391081924078338066624939743691960574943513601028950990946345879527691042763155884466626694340912141418111290584477264707474342778361560823679228359249344375165579780216852231881993061769060447610385392117025495355747798020768288323895196959323981566066483550291527194745396231088809915141831440444731273850983021538690021652902572, + "P": 179633456305495476644478745121183912845812282260996561820651684278948133417769485054620209776025969599330021162710531469071753597272992491297566878175040262328766686012558122050306830396500374688303585129994564684079626922329539032843216111323160853356998331939434583901474426986924795647515801692007815074007, + "Q": 149879966830937345251305187048530685896377646497881910686305551365279118132062308944917220467358982205458928695745450508955000834209315445247823378384214657699561824086702286529650899729457387875724014616657584048154351635103865859801670357534970324990618267970349831585871834567385410171535349170563546085763 + }, + "NTildei": 20150078533963199194774302598259714839139898896697309690703725556763566315615285297141898936401806133650378900082918388544281395515741706621140592419080667964476063086829596649133314098503928256378579770774685854788494580027535784439893705034577993289443483021772799427304806503677893760816374595702035076960135275418924106999291703045546872806766297184177141586572056587891903637044000737379627365986524117500605878979669562523945795678083040667304307087782596136116179610603633160450215867145872322620848283688013867190051781502717153350909059799863957541705709813575770597371343889192192304118900210455391720197841, + "H1i": 11957831462586566144571331364681345999022686477993953116813643158931690142744280667611514384626265150981279934623463858931031965106720806425759599720870302949536991135009571213681399728897463219353549863425956931064622755974939756261102806640394395368056109458955484049875385488560120081741291271972511053571772511828212972259466966570448224805107607896760812790415228640772674302586917489378006149293947929038297964183120701815883789456803653075793335231024497787028733595164656671232595634277367843777691480191000088281555794511985557278392860874037449548592479792581135120514704938964517223098975211661600099567918, + "H2i": 7592999967039047700837485390487123084018384985816136773495288859472209579688778504409361944451002977817380227378095977004076485974146683933794429557718075800125354189446787394373363018642560767902350122172722958370215251173534772534797526969367808975684153048140678245309400656757831436716084724593859583336572350098522235135516507044125865703324358258291181257276966847871973297658819487220702196368139384379447485794822591422572696008779666220857499349514994770800527410715457851526988029339618638457396808579821433906498925250522238489938851058194734453635046916638112874161619905689060916926741755953564661949202, + "Alpha": 1389752109606547981785357276062142409682387072920731659926364247722593774194086450739792829164514055012494521099175923641277101473369245342486015510653195209804221180507438794928831066901134050606399092048081685718752785731273413396291683130232887252693855638746299794593164957274940615175386519830006500512177597353302299928750173306474389714302701736598898418640242916229243975768407117800977372206041188216665253929735067604393869593372797587564888037764392810143941986713008354064527727127422745701976617708139100921059083860865565893996482193372170112451638037092173646141432063156895707669852314520968490821656, + "Beta": 2300988235878083911723048020315969785388403299048541189433020515224556815621450490363448660909459620448468147031671230232514841536135268750637722497799943039235979237146973896045022760773629739625693868544492072765044831562984803514946171132865947359882877284221124947951138383497571402845171838001905628862525699067939430899003958795820553735708995042785734792477209571685426418427972572917538406666199331034299606608175868887211659916833962583854081508932452396080124539811125344315471657907698254457366213692103991957557612978857362557995839079838443237088995983294060028694270206684814996966870159142292687775767, + "P": 68459834157741941368459267334065833602654052138952269043552345416912558969033652974485145901639387546579079909081242608986897747230095924422675198648621644079012209025151852449220974180291066440343156108299340742126854892773095419696587776855640612006142974148970927088642595093660242792682116023812443205233, + "Q": 73583579269029240590285251755250791534196243692532827798245670130395925642279983036226510372887702064780923058906539921305218226297200343893035665189636426192376357483560888547007475943864204989303256276461841661233886171172968920619705430432160490270480430330721361927712459445657975218357730493821533725661 + }, + { + "PaillierSK": { + "N": 24350620792753198105005685618763101935991564875509875828340910596469617983130349014983743221863191086682094746305301621835305948957821128274908791984023473166904696402179959128465012977054852255444898827001716543020108051804405294654684888539213779062548971200429991953649729452013622144514010019954650891778934721854206748157217655070441477480381253179284780148226048001510899482146083165770946809636049380214325952556284624907207240504544815402327873416821716609427326789844981678262181495367148815410925296594435920237906819000822208447668454514131404460308576236795548663928383417872058752836807781393870114267281, + "LambdaN": 12175310396376599052502842809381550967995782437754937914170455298234808991565174507491871610931595543341047373152650810917652974478910564137454395992011736583452348201089979564232506488527426127722449413500858271510054025902202647327342444269606889531274485600214995976824864726006811072257005009977325445889310890208527394526743931207287197479021647473005331309392851374091534285305754517574797108165941681616915507721862559989936058062774145067230503996400755912660162021502143686212554170698050226324622207941442421000576422884153263089880449734662241775743185800551698938959760219883655904115815007981566997157786, + "PhiN": 24350620792753198105005685618763101935991564875509875828340910596469617983130349014983743221863191086682094746305301621835305948957821128274908791984023473166904696402179959128465012977054852255444898827001716543020108051804405294654684888539213779062548971200429991953649729452013622144514010019954650891778621780417054789053487862414574394958043294946010662618785702748183068570611509035149594216331883363233831015443725119979872116125548290134461007992801511825320324043004287372425108341396100452649244415882884842001152845768306526179760899469324483551486371601103397877919520439767311808231630015963133994315572, + "P": 144961375461353318167424632515930704650232664744884119496132286483623806075222719162999846201191428582309498809145760797175765759794147247794772408233945499716280466440561563169722919597892072786435098029231583227911488884882416737637771145907807555915602901752878809369807616487394804726149956129223901319443, + "Q": 167980061690605785562368023351151817687725568529233409944212966844207105459351411458352747102974588398185438303413744130159358619202378020072093015786259284390722280400132742667350234373156289975245782682319495008842484347633265530269783898899113352906601733939271976639055361617352139879027809301512218632267 + }, + "NTildei": 20183828830400964903764707897984639232620457842358987452503892059334783699660384806099556330053591421515147470479933818536169661773341342868209763363775904259346045046792036331805970716837679519844068685898177421663180128835292781717819299458015564883927129809685720028389697806093751538705820808483204113619522271386991083988141104340162099801851480867275772170920535555896968137277196975391681887513706999781729929549324944862481245745383879811054523332335408999444707398502677842779439204207139677245145037894574296099241511632096691568959488435532346231460101111712410194877539661425264999011495500599128846865253, + "H1i": 3441307184484654943430376502122168185836343204745816981139769447376603412213866594450687325505884394613562314312551759995672273162426503262628193262799068101167772811851854875572301641957421123270982256137456067931797529765064336035339931278755670199596283622966319455168637929590452784706573580279877148527605123029127306045071536908877596790088852835601854642656016627674011046202770664421080469098314458528078320648862352636722392267789419592527772845377736710860214867411755551295503326302345370035340714641149188433862677184866102192662515278706718840287106991189238647395024744499352683084309022781603806401929, + "H2i": 16408439647357202389448698242118403277493157708077166547260303571742595985620913938691264692842011571404596982038311149331207584616085624583948295734220843202037266994681862509187807634341782917585499996942806744739278638867756080260212909310419840001125869217600546966988336896460071159735578813020989332411475501144405843752462794132527977597491031069469461159507998139347838387497674406655691238457663841036278139101710027968803527058630084457525317142889967792475785790739708292766219651352147595921812458749151015143897143529978020961473173441423720394799229430357125319325587521250964703379667582565464464321748, + "Alpha": 5671355346430597108721813527841335645807934548656913831955564587532969573586825210648449625334339464884772014392915077503031785291144159360821488087116662536760962936368041386475727249618427283406841417124885275866268349180098922149418057440733481434988364405866686635272984223646154345444332196008335281273097520171931980605414759206836343049539696922608911753561775895273463788525297339020529135083633111708912194560275338760702794605411715475324462801544792486742764271998153905903928691205544599124861278932682430778537845138808168497392589796430262518541092721002250478822980968482085429436027193611128282562017, + "Beta": 1828520595555358928822984209291195502437736931721675493776383795282883661846033810053366338870451524950671859190780001669033845530057638415247007638013587691807466805954462387172755614035951301055570500180853206259627037860687194302981783517614053686862260086883044730787140030439736463380625983319370658804708052958243454100069085200596208340022620232114183262893521763690033580171292001765464395912619681743445830977949814244812970410736126926062872640811458600798402939410199987809434386137290083021823767934152819403328039993662708822719941028646826078751457635132026018381426747035285718245239552501955822728964, + "P": 71008366733698851659454522285595140825678340017627520455721094617776085072979668997040540914169211562167192002842223703072801194250962755786395663026136724475905105353395045056111825449144491505322144694877205591414378649248005185496935689452083978271819426499580869422493148780482520578316137978002068338723, + "Q": 71061445850796510483726212927024449621439327688821269557152221098820033099723872688870248799683829408062431440772108792020521490699190655598701073526967950704079559624097763427365650184966143428581835278784745694553135542775578708327747961124347855266253719149842792202221669420319199577489150357684737917049 + }, + { + "PaillierSK": { + "N": 20465019082892142211080759299065911275469398066579973549166843890136996562283997570615233677893101880524724404549123636206015536311675629070499867110845398044610595541003597762779299098752618388378888330167740545386364841664230751521703934505658203781652068946064639708524549863267771736178031930887525970396721028608377749788107043258145668138176038940506985916224740978450045803173356429531982186482734683572821395283040524812112247163161534579861181979210978603461396320976171019147666861931449941333161640449985918169731274938740439378961073131714341913321517947593801213083808307326201532143356065393423638597509, + "LambdaN": 10232509541446071105540379649532955637734699033289986774583421945068498281141998785307616838946550940262362202274561818103007768155837814535249933555422699022305297770501798881389649549376309194189444165083870272693182420832115375760851967252829101890826034473032319854262274931633885868089015965443762985198217277015215526507613974768426862188558212188996623371488020159839656407212936707543933521390388797875833077237845447160216336534325477901232810936438947259840789953125953688830024246437322635528695091482940043268141125562375501096912436581031282079578187898813692220175434001541071457458259346651255066538102, + "PhiN": 20465019082892142211080759299065911275469398066579973549166843890136996562283997570615233677893101880524724404549123636206015536311675629070499867110845398044610595541003597762779299098752618388378888330167740545386364841664230751521703934505658203781652068946064639708524549863267771736178031930887525970396434554030431053015227949536853724377116424377993246742976040319679312814425873415087867042780777595751666154475690894320432673068650955802465621872877894519681579906251907377660048492874645271057390182965880086536282251124751002193824873162062564159156375797627384440350868003082142914916518693302510133076204, + "P": 150441584188174680735471854012432090815787524968033910810604082287473668392518874366190761254907917656424825150565522205413335605767095314239150200086850945311208558176205500530633993451331419026098333545306831633695489965778729054297947724967195807610759400625849772333844042774706283936172276672506303218983, + "Q": 136032993758522092143621867279511670243827037545705262438096576483259320354964140077924382447049170164730415656784108286266238488743483463156409906246233138468607856548058140956984375605473251249673123938798999999753533848210708130838252244684581946554382749340567000399096261469352333290665095418407202302323 + }, + "NTildei": 20761896462597281573100962165682433191493015259937593316503709113432133462058097370472065788181940409018165769879180382207557150812606659067643562064260917769435377902021235775806837414771125322595362365945350083780305867555082416511309706475717360706462693009887707980789229729298583318987645319713400170308264508285699174506679619238687235462821526298059696428310002395028992781179013803099818336788465971377536551233929274499599365966551522417038130911903295393638770771576697580539912315435778228380909475422862585557793702310783121396305711056128115527119618461376276336147446370574170359699997150001343866823873, + "H1i": 3009012169714659070721966695759722996983175637731881697812120553208423200690648667552071446297170994849340602221585622885608562401901136734317342280330365973925051860589806485043946275048637195666471392402287782957376472399759953625381067472703748108502482827396341291661891863351724904099876651898863814523018336277541842412984619861956973237628817136279800857842078568979046365654616867792754268205784518828085886629845528165688158207276052704962322882860961210169162249585414673794031977988988120615398969313410744981381580119741066197529387064447978571974322515650162063169266721954425398737908069850511078249716, + "H2i": 3848055292687357360053024006649482449734078153391417166131941069686016052882398478307089585092976563353343726772167549341760796400210070957898766539431106573339585836856840334158333351700686112858861881138305178225905038378213739322068843421115444603615959625980169384617236160322915149772514030585562453509749886017086560657551571792710655123454070336424435184266730724152319586273664684277896348858856675160694243820883256531997309137829354623547833934966449167531094244920261809353519002444149255067822422964079506539861314635909394367784613892805660945765731211464710550440355660335835329773704441530225025792983, + "Alpha": 16821019065849584516365376322845383615245796030124593537994171808097853951577883840231840994134020267802121502844340420156324136024427045065973275627949186622403806238688888799921587310844233463519349889606236925475581245130227287625217215201963501824991457519187547953771498894535395453798446527249192789168790754031643032207926368663204616658483884339901051609924258142649824465298111351082056307412098073460755869051784054535205563076549259994355423900917276045978326354321323853749403912408721249643571671380467416566745796512239810087957415382964749782549843395219223631816393023755885959079183603986153185380099, + "Beta": 1420991908910845492196205922100288654230868353791404758140714855414988527569242361550919162417412548829549961112105547043238187664815358476884104866136577971032191546386128727738341551610098984252828101684925255269155591062328393853183013931780963193243738418851853946173990002107692276750315176990973796209711182469250425164271263000728666438925946217223414510401671987209587309910516170602885721185797302020813684748315806081887535510665759338572373983021509513849540776442801714032720092508336992053769538414743954767623723112417254861629697741471514431517838773941270763856435866415106318444111843186597359305734, + "P": 73936331215093752817189388253867799543776277079566780006435422091479291864069293498400619040829384287398896454865561960320190841667002881950475602646950342079189230892904420679243145394647969607814131941035077086306953479295640378088435049737310881813430875907556289568067129019938024619256878391794271332053, + "Q": 70201943081937904123515276828055660984867827993548742225742133226367564418691000243322462562353954204908467620956541381352061962081762467359987964885645181569902992946130820561808832923251411558253382180948283183209271821485954928765504758234397210595598479313721919423626786383667101872737659922545985329569 + }, + { + "PaillierSK": { + "N": 27020047132193556559042568701500017571776207559743813753361337046541955790686397099262657270033746387819915569714728221505316188425793461580859370424873971323309570120466366177054513179879244433999611260252894481764883122499815766651316166612813752189312784106728820443912046083469860406968728686963401478520905405226347107194117865323607069112095125111222428253670095608791364091636569543495730655296553784279124665586702506205139285303778067833223639467842378049654759342063358586743016539006845059590835514321542147756168216001427467933911366756207369567190370321312874213614476905414506760509570886363998866876053, + "LambdaN": 13510023566096778279521284350750008785888103779871906876680668523270977895343198549631328635016873193909957784857364110752658094212896730790429685212436985661654785060233183088527256589939622216999805630126447240882441561249907883325658083306406876094656392053364410221956023041734930203484364343481700739260288013701413644449185014907764212475746620160257793297301067147166261773318369665836440002188134980756701979010360242875125644069893951117575287957401095840081922958631120491861674512462309462986791020456693882050009229460969920603600133670233056305457712624059575836086453602469085042663126815696628831102134, + "PhiN": 27020047132193556559042568701500017571776207559743813753361337046541955790686397099262657270033746387819915569714728221505316188425793461580859370424873971323309570120466366177054513179879244433999611260252894481764883122499815766651316166612813752189312784106728820443912046083469860406968728686963401478520576027402827288898370029815528424951493240320515586594602134294332523546636739331672880004376269961513403958020720485750251288139787902235150575914802191680163845917262240983723349024924618925973582040913387764100018458921939841207200267340466112610915425248119151672172907204938170085326253631393257662204268, + "P": 154570091449735384194035066224750886223788102299636466210189326173798609684824444231986542228590989245189965149603900942121629964822885398293646036229151300605012470691362777984647296913005971183910976834877977467887174424691019032303805254755010299169133205013364136510342237928726339627711065364367230481307, + "Q": 174807732070082911553800441853893274378096688407205192857771988285041935315005767590864108691692833520530742416378119512766367199167280199779417516811035068885900954109754825035020217169220162433342496573276406188262582654796607694407294160986246657105811868180358404931227462547610335555606189606373974190479 + }, + "NTildei": 25190236164565450311018983996173433003789562608279703976692903891752602146166122082563637117632510852615048504967282179498085192913519830192246741810107968110099786983766321803202071617535321911527107792235742190699038030684042785512621408802203654303858579995632245896001507821641342030428714881212996573132370788574191832941979019509412124158573581539319733188834668063712611601800801425374079060485060788048756937518964299394907607249343869526008293232606476968639266337578587463220029721372047818673226762932818642193404680862997741638050068789986525173474958826054668750867878358959251721234277830400098500772881, + "H1i": 11465027757214731165087612655544496821516913927206672605568525895016058229875742785992083634557170698550197252050981412876792370377398970744487685842715898341248197203908393022783683969388304312040070243947950817998154164251277010631104625105028268123408811427784128044120352537986616353753984802136200777554582665133603272778097611629218515383392012140178079554080505547204501011151200087164479242119696171850081727268681766796879346608621825272322723330528497124495682149426796624543125842985847788058699341069923024397623501174140462496240596206270738552065953163059142738439977861071215930152381690600125849000365, + "H2i": 7065272195241834869287316994805348777517110666197433296202304094726214978541033176123249053111425788021460220112596936725698516936733802800821190677649776434940297926321685607511925301557690727926327095384882191716912341400876732857490647109414031477631343078060265550052776227338804623960447945390473885184865370953694856846981873213250221348645492688790195516381269004759020222899235419188382883221447041640365928147203883294604383277350557053752914044036234251886546278852707638046180674773104212444240303240539649582447661227302733879323313515466413788276264784273184882668283285982608961524095716788622894847270, + "Alpha": 21759542422464569608721312492451746998260255807023234211856018055273228925497052726720404505543750325699982720165628205952809301220274080841082740923774763989173878305520485725250526006317181843418858877016824834931393280045670801508256242498125661700197238337363160970195025844582908003063865001230212437476640119712321765376624217832962858915844397480066917187159599137605200255097074754893133902609254719117180451360824820337942498675940895503429404748122178372511191197833211646263556882713507004706010092940311523170164979524501314721933602128421168343979983135452258466142953036367262770846805724456478760421181, + "Beta": 5970022635942781476439593106816879376247433244867699715475807611660494348611370710841871959750197101640505770406168616770605736568651506560593937767218868062755521955637678402435755282803595980398074144408749502081112283972256050863911532967232169352168353717281769160991547649489978796203880574272561131163971286189188556184484245602599402924069518260240366501169238199227586082184225688277600647128062357371180480820019431720362238272029634287846484906845815291255221021191869769424168515465366330262728309377088241655588390682567963356435756505529505167578410936996443917229025143081052511795535359169152938668192, + "P": 81399208525252074588980925797775439479694668514254912061891109127465180399918842751117202103712770017829220031337403471880996374365542612128702347155167622426786996183829788088190015953982385135978793765722902094952478804420533700066863379783840738824518693498710644379455725031603837323327351851726872317463, + "Q": 77366342440389969243661354652067512488911504444353398673843869834581199970847068934909805243570333539182052201810357223542872273071705207252322595561214669795145253906446874953923818671791008176970204114624302749959719436194567791549075044051851214447178570730003068461875852271615169444887127363840192285151 + }, + { + "PaillierSK": { + "N": 21767501586197148990048606112036030928969515183696914317708400583150325130217478586706257896221493477068318915921490444862421291785880136588226790734674257038993205935689799005359467205073346980518579322869692714921580432349646448320308599466233732499724371694912941963944509595214631511710323786489119971470754642322066987447704854168630483519920474826878691967127822096053262974073457152128456625014277058630686833899431493143524462657272195131079279572150773591093629677378945548661881962135779647655197639964319061967817987200972039064142277569619573396219315057199767316360159737264875392610688190537516328233353, + "LambdaN": 10883750793098574495024303056018015464484757591848457158854200291575162565108739293353128948110746738534159457960745222431210645892940068294113395367337128519496602967844899502679733602536673490259289661434846357460790216174823224160154299733116866249862185847456470981972254797607315755855161893244559985735229263493032582543133637917632012318285025368790204338056300936569296178953549597506008304309627373229740359764809175824533107215715214312313862502490065240497396313170190823631900234661210486061335109810907212328776710741670926405965960202955621300868596591459863200637639435303608941814478668372025184975394, + "PhiN": 21767501586197148990048606112036030928969515183696914317708400583150325130217478586706257896221493477068318915921490444862421291785880136588226790734674257038993205935689799005359467205073346980518579322869692714921580432349646448320308599466233732499724371694912941963944509595214631511710323786489119971470458526986065165086267275835264024636570050737580408676112601873138592357907099195012016608619254746459480719529618351649066214431430428624627725004980130480994792626340381647263800469322420972122670219621814424657553421483341852811931920405911242601737193182919726401275278870607217883628957336744050369950788, + "P": 160450063559110959012904519535975842840594604275703356266890576805667655073940288217779495645051411874462292334250768308675526958809879940089717877393403206307680635567258739247151183368970753247177330286080865387301302670727032181776553548399958210145244816181452771072484029634600203155514332161461660302139, + "Q": 135665272442711402424673813830483040509829485022579934748329646109002961092417668898660520749970900296743822035562373185782721267031886566361836689777239903791156415471305162150930309444387922285350090056423771922963263046903154070433803615308372584336877058098588144012396837023057305826216521632004297980427 + }, + "NTildei": 23920428680532483995450188046702079137304192044984132642479842042640965411470944761701941020339697847333242449366214943551501363126698780053964393582814914031481407555051233949234241940831155258051112008067959217730719548291016260601919872294527627592764084604508433317546125452781003235745278471959217522761591443039712270814642137441502962846456645441112867934321980868351940807608076088053740207627222310606294829694140109693390565363115980050010705502870034536225757584430392709949026040456360695225367828467003026193097481839285677909363407855137504423355546095952325078647868110490699735422540438429286262494593, + "H1i": 8725178802234267572755676827687854525324633398435062936204214458821611668225003626533886991596739457734551771377129519672879165233815037036454967848234580293528657566217447286335719087567691410978056744944430550435276640115774637783833689075744513457315744644310610885962354970205440226790972744338079531858495848858477036897720865485769372896219302462222945100431257915841349654520812568181113734616916956113964465365323657234715268795764463220367277818473830055077964160592618180679965513344787319648979000600615132289606074842580575738726929984557328797993432621732887960796916866175196984710580948208071209882444, + "H2i": 4935297025060699529890782464382458843827484746450395962062530404158733300047177494790404482860989755775226917744545357111972367580878067059688436754809833620213597979809117759333104857885348140206349663352670632171676355498091443115446516567040640119245530005136953615602684546990550144716736501161286882277407003585393557736691569942506810404662459596630095644309234227476549525861980935333759401140150599833993002381266749320125055064912142279603416839768024562640165800068290789681039562712820709711223867309978542299326525249493360672835064525773623865182065664075677185911844930579801106795591825403579158686252, + "Alpha": 4122039064359994946842456206543617656785338865824536032469257008265026494378487499168696863163341900504643816299095895606384653328594728961497196004412338088929006723664073971267432628585170107957971073802716536919543532625125403515689096760752770682326546443210959293975629405688128847133273963383508407257504071850279663011928701303274269022117947038210517579607927350729348983499664606487398332398558714594276562033836290243182108917407806645687516609872443627810934703930431931239477554475139279965808793938404432218256629402394266701121767314795034036394874891456042743870837779054263962728813411106009580108309, + "Beta": 5285585314077245718885628735370659295312504173413762484973432679171062775768245917227087666050608060298829017785039438360377982281695877080936373708886091918826203975127231675313615839442810761197273496584458632521141996731072263592671402009526010620047410750115623688881323545633918092959905145388020554565788545217338904004221627147085436413775724525207126025239179370282893624596104866837059177785464833375839778514358036995581797813026687584282990514415978502928495254588644375837494497655066266380199411963588726442176487585237843257287217365874886883092682536519395603857305052217419713048180964462986007080428, + "P": 74240877399996498621731464779197518965403957340215006398111834847540109515813781239517088511491734475174375600436252769002750543474679194975548136563948210127661874919400645605218940841717010922432899886826997690938057598119053098727885973239572624160339360516746974337991516944913256328638932902222055916393, + "Q": 80550060553748291707205754306698091262911386013019678502786906440661124481547166432924287423759447287395469055172196328128567269208696932326765183093480781006981212112275582710956493009420374812903134323108898602273855214744928929997410536422467212915663259767552718287283506356920687123316315463546692997869 + }, + { + "PaillierSK": { + "N": 27589893972975184579091150242290615415839441615583462592516892833454191725149625170962578770346016971138822607747680026830411483231569106174659704081008959082572948689490869598976416081091423868397949778346098379149279306780010514645575079376331086466440642831393554243818938113085240004198280255757293758766879970549085748596558123058794705396377749066456888182928576481204260206849196457463296845972163154612908489397285615833473466793219196392650672873068973260036725065043010335661990720941626807725992011964673245000492542643186691021807251076795149901011342567798566739409737861652554770208623175046998908278569, + "LambdaN": 13794946986487592289545575121145307707919720807791731296258446416727095862574812585481289385173008485569411303873840013415205741615784553087329852040504479541286474344745434799488208040545711934198974889173049189574639653390005257322787539688165543233220321415696777121909469056542620002099140127878646879383273389342572456640095914971495782671569643653785448228092131435923256624166295757143669884475447542829799836233315632704657071707048909237908586665507518800900596380935198711704563644444549968570608379304582345900636486379733983779283943433980784310374104555486394076930147958263099885971676429389523045697122, + "PhiN": 27589893972975184579091150242290615415839441615583462592516892833454191725149625170962578770346016971138822607747680026830411483231569106174659704081008959082572948689490869598976416081091423868397949778346098379149279306780010514645575079376331086466440642831393554243818938113085240004198280255757293758766546778685144913280191829942991565343139287307570896456184262871846513248332591514287339768950895085659599672466631265409314143414097818475817173331015037601801192761870397423409127288889099937141216758609164691801272972759467967558567886867961568620748209110972788153860295916526199771943352858779046091394244, + "P": 153777563270897277702079974031048180573127425049075807578070570693337951606722247114821066014199592264180676436838011155698165280776348164235253891781377911904954513752677474642005842229581030799165779282993948042022764427390395776755646177857211488935636001792567243297140572641660164496744644743139966944963, + "Q": 179414300669938038664213141772091872665334333836915919166243038664409006909882696061136011007068476689128140493816339268461158098345029752598245650272557746330577789419935437610857589822945839785609474072514605157196805456328327686483718030976369791327497455033211342252301372484694833768525671524812849939363 + }, + "NTildei": 22842412127118898772274658650011562930634868696511993449561784027612226634962587970659594670620200070152873058380090508169109984516767819005670747302246013407258076663219791146116706394854174805786170713408621552959612635264160733571810298779956239741629161288728196002857232730998745036663460100061993582475834259933837824502719614300927629666645824017466634169639449628545588726371189683409955206801848780701126546169048871185166832338414267107584432452560552228793876065087381637707217035268450000111855624622887076027517522494323192132206985863364258000042394695494178688338347621224800942058176714815577469850081, + "H1i": 10438728166063145554365692329540251857414804242439727907792995064405305214073883066324827938160577447229516597572366824497302109762124109694665167200025720501171703586273638024584726876097928269395540599404224398394867681309529003453214910339669861918644203719700904110261928149902279405383927473380352210817061631164653811421383097832811100493483765945485554800543142879126409962838118510624770010916101121899206005293668000078865804260045416736720792734478848696518639038799541192269503072576805466314980162178592469211194620391535116381907232045061261317636065514572489111758290150500899753505399157998387652383830, + "H2i": 20105674488089683353395616783116056112902045363957704080305480742882629899282762738121145229678530846012266117681629637874471359476265562732185333614692886381535647586855357159940081716128075674898007446314719238705335417028035265327399653459394190831387534476295596652300273641708270723346897064856567055762122221083814614217288041228463308209976108031646116106796682683903046557245095512565191813693683510815330875929856119161090940752357199546488689968378438504036057808782244768777522701460510219974365201720934526068392749834414066852306909993496545721993154119849207760700627410818815005295929608672950655903816, + "Alpha": 484449185422062416207968563615619333063482692978197322364997405636113245602538053378348517220028462293694129579440681331689034238612588538343374226467361354787100909527015516032422289963732205520542219381778180661788472485792588810106958621705063426122948676349930844804242270283080247960827028507403406241676498375162076140831282356760020306683698448561781320690645994274501157970110011146795658917990831095877507188517221678738481646738875163840101044831961523550920846015209723802855104849095540126371384539608932349022575711139589681765573533689254240287965880639473664657120358814451677906210078145720398850843, + "Beta": 4066651017730978989491257766873143087477727853069088654772728674437452572453805875641027489716501669479607522740636011086780678867143133555320901607213843864725795097056608155799707887322592690897662465353086015269330536558012091190017384349296421627342057509023565858431642156706388765202653599384160436320649355874395551677555187836133608605581979720815374961918640584064270355905328935225193687205622575483693655765324719218218843209919161612446600127290507071166813586983225423222540560376813889828745277230482734527731439237335436840468333629188190970820568160727737739982917600339160321364010071266797787143335, + "P": 71411260264002239684063995616266806127257816053163408758122801371056562990939259667312370336272204663464683195367028554996123546955939032176602944274062621690280670879007657468372530374278662529957592235824323581490202210531332658865446475354057951414847395038613628397202927799233325020625910252268927775811, + "Q": 79967823150971433336326268592445981272638547011630791401092829777946510495925887285401210456104135437132052378182196783826654158191780853140300835846734861771559078205545083943261307752058087210088919140147304042088640995184164295951206850648748965522443460622356636260247105200832719155047249739026625825323 + }, + { + "PaillierSK": { + "N": 23278255699771527045615142296617020100962716983617509514464060818600742789744003898025772349460166040252389823612058719330045269834083819676524975472666375857668239880721560447577169234664688954861530459742643564212438234158111012393448757693998112611796787818066385433271058836342206862036645246085355652061572759344926021949565990594429645037552120629525062521689346954213469049716378468526659556045637760722209780529536466150184862098115435230880686594842114193866862327797183432090985977585622555184858955168402581420639531532048354879196199660145415717962894727920898791820522587429422725339362965394105862911081, + "LambdaN": 11639127849885763522807571148308510050481358491808754757232030409300371394872001949012886174730083020126194911806029359665022634917041909838262487736333187928834119940360780223788584617332344477430765229871321782106219117079055506196724378846999056305898393909033192716635529418171103431018322623042677826030632712514465787601973991208841807840386404971368557968878002063319113430131884909824963298401412134403774779199142877839253654068291459395864312280951553078064814117793247484610524452884476560896175357439481351322108881721723161534700150518488030665772006947969553125046774776216772174601310994004434925542186, + "PhiN": 23278255699771527045615142296617020100962716983617509514464060818600742789744003898025772349460166040252389823612058719330045269834083819676524975472666375857668239880721560447577169234664688954861530459742643564212438234158111012393448757693998112611796787818066385433271058836342206862036645246085355652061265425028931575203947982417683615680772809942737115937756004126638226860263769819649926596802824268807549558398285755678507308136582918791728624561903106156129628235586494969221048905768953121792350714878962702644217763443446323069400301036976061331544013895939106250093549552433544349202621988008869851084372, + "P": 171979442048430205698847260547945242675062651327606414600241220416480488834674745715709524452963996359966609575227314341709306876669657103743019326266430793745639801326876988246572154297220803062112897289800184358639709837189230610611506915488631068873732244058748210099215929828574760150720398724332372138567, + "Q": 135354873946016539919160916198084114104248035460340169333101607158761700617933903161023434789849495554693612556023396129968247084862859335409042706672577243991594290883811474623364917519448630330395342999639694417782058251412801199184391707680723317545148587923044331627757105167303615986020578660903639688143 + }, + "NTildei": 23615726705702178890292902720783515145021046679899814669925498966844529754794676140383384650490191313988951378455134586807867601886226492851526261640493882104822381585184949331849231792001901653657103967485672032986453447954044856857809966370816177578658177643306923053365756235236788073610478360379135448701449832098866816886888947720443589692392440456607275752411084826761907897214249129163589577231222062630807596702559558204578906422109996720837354734367793898297513067002378897724892468014688831652993317010855481891858484950925319177395595443473345878912751251353785813905994567443439278151636023377040671323861, + "H1i": 20461096972928137985641895979716133366019606240609032762599556302502321216927570885782363659822795803290612026987915427177408985647606605736013363212945850343034852704962021278220953656640084627872541107364649992296380179795965949640043331995807019998742837352769190766202076845382192958877894536287723277955266792972929624235774942320818899629700999645744573793772104452753951344294650306984057278181726643066217008638111438814983220554499068266608819765492609579161671832853295553005318480353224271993011633203109300902428467048626703146143675229690056606779206244336198861613626885426810561968165571900379893550110, + "H2i": 1693809815279571637920606449665440098032234041730472388750908832760431088050787832962536711014150842686725888723230223600192180847188929874917389400293549146596563521823932809766057856501575719468382080937515009248279378248748068257113617125324700852593659798695690746719227100401842708895719451214219550964360078535689581138389844537906130803180733722872998244617249517039793317714589886891308326632430152584233346775754185301948002019864611881590820502521483450653887929518166212515257890016330745982275464629924664211664096764288692264027135191945528758768351048012506026086507404380543266172093395915050029636750, + "Alpha": 17879442672832840843628018791180759648724656594566547332558537483382703929027295702808418953050594610278798516927339254960873799530982461993323945965739557868936821873428210101882364949183706036097861781770987916091547969400446476051222125585282286819948101226422712505558946862373030101379047830980510829675316570895270795214366987698076638020025489841345054872203460605311988312680581559121359114166419246306059513974141619705843649125975379264821126228393517929074061402008072583762322798206352943289590166675697039458026739971581943652479059790739577907791074412001019314860367263415080942026791097753997128031627, + "Beta": 5019154986559116001402021959582691256584470128022997182433265726788696551151680127200750651809367666435414836356446473707352118936765029243710017268493971084639025035885960608123720896040567275867165964431242948729035335968243190378886104368164709121846542454520566488729620792132168996041814400963142970055168421328051446681697153130319100506521755599270085807155644545916761277108826530226630115546585533508053686352166499683649475143531781963173320755802859401930961147515304794591714296975909235568133775421423861541270325961624971554388904109527462501592637922066231522778128496632666520718342164482741603894886, + "P": 79306202079248516218813185260753110322950895596909550545700704424996733226112121176975855505237791912386755132088221253906074946600937702684519939952719189470353502115209111582484794702225658310311790166618243750886204741946421048714450794990315059686178944358173820563943485027778097965459333631374896398701, + "Q": 74444766255808183281101449595164831864234857527243573713639011887626294422268033022624149705114778128663101533699472987343863086051519543187791864039849419576420686116945399579559008762199899685504219434095007765682726275434246560729458161505108510880971770852532695190409905457965021109657748421319485518343 + }, + { + "PaillierSK": { + "N": 23025768238896392603290928541273159383894320619061814055280543312780115622565623990557501704304878949078110786051980996269653113071898528057704365695046918870192831755495253640119148949778446697422873914625413057610737483951727386478571221387527809147240820441510016940959913293305346451555071077738366810924387763881721201769176936957949549313323949366770342848797417535225449218665027176911296383725992255482822449945028182634314716567084875126698914950551374254464505225439667404313637201376939555917832653856436320414555315228966811293682602064890943978607399339207605027992074342674422251001837729389698023035081, + "LambdaN": 11512884119448196301645464270636579691947160309530907027640271656390057811282811995278750852152439474539055393025990498134826556535949264028852182847523459435096415877747626820059574474889223348711436957312706528805368741975863693239285610693763904573620410220755008470479956646652673225777535538869183405462041466469827932890508587477309411467419536723128939029324185412472275962223702328704064896993378392193304506256941850805736999139638962537344680690072877828718833457761330102369290825969863630236270643712319556401121715791879310130806212504334958198924491190938182892915125911810269338742987261111832903544386, + "PhiN": 23025768238896392603290928541273159383894320619061814055280543312780115622565623990557501704304878949078110786051980996269653113071898528057704365695046918870192831755495253640119148949778446697422873914625413057610737483951727386478571221387527809147240820441510016940959913293305346451555071077738366810924082932939655865781017174954618822934839073446257878058648370824944551924447404657408129793986756784386609012513883701611473998279277925074689361380145755657437666915522660204738581651939727260472541287424639112802243431583758620261612425008669916397848982381876365785830251823620538677485974522223665807088772, + "P": 166723076395329623153138233725424789432926842829204828208028687637493652202221117279017337731005096455600648361568251071421103975437387757485896447738395660715649441601232359697695895752456932416021006363483391362387320980020919921547307378256751709638081758968963430804289786008266771058889634916673807136867, + "Q": 138107865670006365006623769605301589051949077683259961941018022643403642015401402224149252008230374640612789069576229951419614312369562294523657122667222936311188868315774839877359653684755363029270360068313816249924562665187271110522869677964275871120335198362275811357532733045616802456973572249358408809443 + }, + "NTildei": 30375374981035999935225575584436675947260587956649627810141364906284018011860447174765346746173399308362968124646442374593432455331285179083199220472952064681048409255116920012037816798463860752940077503715720485507474298113873824526951988201025645572601115915534985919465533701890870011041792050750892745337574123724742322243938667304960663425400879143310682387666755322973104331825971746783029047854005989493676627478228644407934391604965123064063345481650663919751100023093847906736732818338397626859499244634247240694224592964903024831693021344610866063961653746794435130025913082979415482600554278748322944812153, + "H1i": 11002899667082756482718336472435947792678151789832573324024610460014042044685684136096690594899448717117426286293569812050408245232590082618305457370163481753788542752163615671205834298327857879713980340420056136332765631470874019434327955257442632176746777365709775594498350437580613911581411834675424242008060390684688322186244883633140194441848948049600363866334244206115977239020137098564423418183196744233240639556531203606527389504246538686235931669331297189424949916461080627383164599739522510124782564082625168778331326727595556178794528268147118927615795092634709580672931790114218716143069263296170876538360, + "H2i": 7029879915884795718901750114809064618561587612637259017728329591477459564598614276790828664688167858154279021630088246691387321261374879092363216410369473297967926757450892284231426809767508109986446887397418914492044318651763740537941722747544758155355144015684529870219045833281081116703489526830882103012894832236415191223617761128371723128499157180346996961088822393734391815145921594578283534970441392498975325192632682414321758860283324584046365052560232510857897844113569493408603047956549128168720393629999970640489333490433327506308271009635668675715069529675986420055416522567424517449300830970332373500813, + "Alpha": 4014810643541110834979401829193122954636993727950191647153558933872764795040289896312391245719293866835107254673999905613532362558237865533061336613154610448510203089983434809675712576102260274821796661586219052210086118620533127101545980560064015415883044600597937466721307006912290961743738203227869538642598843731657859865066438872012842255366739946936048455374250961814694852769424339780578169080339705264292108872152593521865272428588822282733472563564145916936446995323224123845402980337012633226312552743129392354008472229739076032936947340294901702996748906960400400878492762370531339141583602612561187434947, + "Beta": 7425430664754898013521439098747054261139446148656849795520121825090786468952772043516627824025355476364545859123361332916744259892565247599918865155950207012193707782950424809463420019085550310896052166791745555855556971524139630369309737971637325438582751858067256665061221437969350407372356218861350620058156086213663071741743065201061219287012574296388830163007832344056279722593541943972469128687226174620277468335833762801713110359025490236485134065674724506815032784360187300357400153680213433966900407175103973051724093692945080489903743744779956533580265127085286594297928316138654718436469790850505626681669, + "P": 86233605799910252289623070723664799268428035030546754053461661780732884979093687880579066796930643394230380304138921862243735563215377856124376619883533524506823366804836482497024485496802840665699326080844954669822548210787060034756930210847856064083996956664749536048580940290737225730957397153082491639643, + "Q": 88061303650912661756999970310532198461807229722586869739251483766290250492365458356790296637339781450104667445887591154871234999095895942383060673243855903671790662956397552974611700013450065085186546252465316436249640962515441760093323065508650447589251481419502201394751832985966954335417711938223429835559 + }, + { + "PaillierSK": { + "N": 27758422867008020711780744843446342880191737267244652357944508150157370454433129476620918339916887217209504294946707206450470891872330524389470720261462097922985542215549553339357040637930748384984537167001070193776261862159714617069124812523508089766867647256778225810171629423455564086787714104376158506171504413483151433381328831756556984215812865922390580829627363531845684653033849123776506567447070489154143216020187749169707782468190091069847680352086714071028150805374195413855049165883999095525671991114231219032268351630208987758605830726277601014819043750680645695767246242965014783290410618216620923430833, + "LambdaN": 13879211433504010355890372421723171440095868633622326178972254075078685227216564738310459169958443608604752147473353603225235445936165262194735360130731048961492771107774776669678520318965374192492268583500535096888130931079857308534562406261754044883433823628389112905085814711727782043393857052188079253085585462310252903377447245907501484488912002118494436179973191152994154864773992537076853645379102175654454095018737308380946819569070049349850966327870724393105032634291116829317090080290714015223927298058587411420771099832597251273847362979079190766951653424374281072111394481680955037970869289212049940164154, + "PhiN": 27758422867008020711780744843446342880191737267244652357944508150157370454433129476620918339916887217209504294946707206450470891872330524389470720261462097922985542215549553339357040637930748384984537167001070193776261862159714617069124812523508089766867647256778225810171629423455564086787714104376158506171170924620505806754894491815002968977824004236988872359946382305988309729547985074153707290758204351308908190037474616761893639138140098699701932655741448786210065268582233658634180160581428030447854596117174822841542199665194502547694725958158381533903306848748562144222788963361910075941738578424099880328308, + "P": 173473659373666163877398034198726314376725928495419419441389338286631746484934960673336679133305398341985633414024089292432724128027106973903048507311573189494677912559997338066626104248908470712146719478264816651040536447954166002471431725522523159617055296461205087429725879602370799667456877403453869671419, + "Q": 160015203271960462556941907355288923612135756906289050239591887570743177000929088949462597555560739503249392568689043115381419202022885396242699189033692095323407624231964417154242901053662594365670675518791579539685615517060319208439673042596696321298681605470878464114731400000733907681215162389067173431107 + }, + "NTildei": 26056261811873951356485767975229520012945914828631514605812154487335570343454797694068327616179872169848481364403334790002351759621520859983578360701473952050818831734652199964355555393352991711900155529558602011915048760275706030592541474870787627639829294177734685268552603911090890717964959153288763943434856076720115358182843246698628856602125002496759476016535429741864696780478341593305540120615111238788193776497414561779226807061200650141795868551557308114861874761842615425752134488093278201149501107016121526252409116829732493865451170078078517959720712664574368968043981076277961998780902584563689747929129, + "H1i": 17337051403883435683795251465667349762215816831015718885261962124326561992016376398800010735731393134122284125267332220557250978673680816798504552576119062226586551981970092674919239815194494899426494327541785910198456841505283528660377582001905738408530053345899058975162034139220903646419696715576416724167685840873625482863285258961679569342553735287859625999276550751172157490113108297775835349492467233046004820074716473372761191667990908751815009480906694083564022902440520300987798137525651570087839946453183570762447449478212365639530075273419972427705823134845743616693348308050484570004759052677174176355715, + "H2i": 11909383336287391034274526190657051940780659980526784998885911824946902488089296652808307430734819519218484092419044726286501688633090795518634437262300723354864831186952584676564969139982346561630689780313489043969371156429565217250899490451951590274904171577435944477648467311929732374048894073133771675611752709268788044219107889447628926557910546943067474767338750065034342778553701127583446918320725570914964581677747160824526574897767808534573567724354701882322820106968943042181096931104397048619888442873821974893806772411205015831067804928553706034376678548313118714919072160094849859765876672154454443004466, + "Alpha": 8027074689587172871716866331934648907316836216973157387407630498884862147700962623416024817908590395538137866709395227507376956066146621927901043616573131770765398386742425595539345897700440859883796393816751757419816623478485145034201012927265950307979748072879218814477983167692254833098735695868720845054691062221549349277922139271950497601561440860648750720510898439570324573774430610183499701953937465268754529227415306270520024304826936258702870938822048735316258780217744229788567884920678778740107186703367543804841454494333324573432207611516367476171395263504868239411750510633203965623985317665646858495973, + "Beta": 2428888370167877670897696706036495760922343955411380763652168154001455226568480004987787822746646018989113171296972428327370618481673774063619789537223987981619093989780390566917596371975311131589901828851701048670240368385996697015445781868214486214024944054374039690010459025264315689753170280418004470772154669076134250782259895233507773016472778658000012931571893768241347701736631654474357006319945692286162446273485321423306565136807081229716535126941595397976552164658201652982414322483975857279128034474890119098662289111282828268171133847376974066443803370041056582591570553583855897594131017905880257683252, + "P": 84216162721882122033878644029519541014090400995237137498408102844650330611447175130005633080620654861027987139459750750698860453419128491538374222814235944346837867247371616004283807481453342390955718545054010420534137131828634585190576951253874849057912837990865203675356533710953627111269490860703274851933, + "Q": 77349350082367501664592884332312838206662753874070351224196745480642881076093761061980588630971740852097909045308523015048488630332956887252285715861793563241160463487209335146006424009725216197689354714652815062846593856118538346578179670624829246550925586647613255995822143941348242746026628501922045559093 + }, + { + "PaillierSK": { + "N": 24698013459547975620768486310441638500610931202769699714642759997955116547307259210904552657285835134313163261128234252079575358844781812172753259043038366663041844914909382377076299899058958586341075436422529959183013628784770639592779190097827596158461916230746440160460918439423703294778400524288954854501183065202598966312629801371774097939539173801466455391807870933284832506746505416767335334466013477036638617584074761829555820151716267792125509630870822819540167483062263131959897949873404971801196095194873685707169878932263603148545593452924434567638660822083010862410692567940328071986610545213865762919449, + "LambdaN": 12349006729773987810384243155220819250305465601384849857321379998977558273653629605452276328642917567156581630564117126039787679422390906086376629521519183331520922457454691188538149949529479293170537718211264979591506814392385319796389595048913798079230958115373220080230459219711851647389200262144477427250433003143005297950462616574028060424320091474597861646982998074762795042329941848644071685447477438051049219216091748416857344220490170660116220843678676528576428459430479964866722053201726520200468436079218980551997418366217056795565545185703505998949004538233939377306672833020328506254113321219034891677618, + "PhiN": 24698013459547975620768486310441638500610931202769699714642759997955116547307259210904552657285835134313163261128234252079575358844781812172753259043038366663041844914909382377076299899058958586341075436422529959183013628784770639592779190097827596158461916230746440160460918439423703294778400524288954854500866006286010595900925233148056120848640182949195723293965996149525590084659883697288143370894954876102098438432183496833714688440980341320232441687357353057152856918860959929733444106403453040400936872158437961103994836732434113591131090371407011997898009076467878754613345666040657012508226642438069783355236, + "P": 137706977954421863034824891356712290363794633078002584712573943198087884947057058103142595283928353989425520970487992175668106291406224778107858843159734968039378980893140136382545510100681519297006873126985494390385762437196164009252987130491384078277140825447644281973603844450359121986161434008138397885907, + "Q": 179351938633948548669743332361264800535196219192729513129300840561154537139564661376049368287130246945114658181403272820173025419329701693785209100353734794347931583308163065843908333369270412103252349909450230212789279762633325548161515951026038491463510920167487825823743057449311937492222468767657581678307 + }, + "NTildei": 24690422989147079244331941368070433085466651920553999872824548273581552535357120135000911604521136634710519555286289875846405372918001804165373314164562321255223787113687824913759515848874622094464554627298322659680016818468804177101671951869589058029823229312377322809609112982827997705740693123958029295212552850875435775791134220001046174332855654026068089715299035900787889119173017286792570505203745761312967763842094587925290396463221870721431436845389595408449410670082376354849446181106380378103194199593434589809308460121970844303194183027598598900864864755884972326878177884870736736802032626887805594537073, + "H1i": 18160217679830452657187821763041172090263889388861593820249335706071962684151860423985497229358454693954196412986026677217054321777411226457788594799227840346213571392881864301794083680938872927060963581147057109086554471369015970917818102756628753094521751684846961842998357942002291416101399988242970427154989501845124779251784449001656693716769854363201099524714724151681653846080001290989219062955141437477357929821127788912455713684500175763472483981033448604809490825580691644343341231568488550048731941654578659837669480036582211355621746925184380400617355493278667045571509929146811317819599518255933973666117, + "H2i": 7539909739099262713642749584133631605552390296999256248430709659613203508885331677246698799836601923388268146874402595192676776250980640170779224962773530092755461572163698224655552828772354202127984606620667116445697538062590812517574093672311583704096346609772879388167524016670756329286726333335675524764888348590725818945115080363202291053953732005935767730919692745050363713686359888571746210762783314721367082082544554604421530838727102637305151829255843914970681085131308420369957326865445042611666345414642816205057840869177471083996991269169417372609376541125761996574738020596883716464578915933111084092971, + "Alpha": 17499809289545057508247053676742738858699189284737603417523923783264272744066066317551899856891339867717992338474336099860122449369482625509060694782707572965999027679232589627632818656360950659290204480986385688824842245964146817035794861093222535116000152825551339090318847963991962322801503595572757693229255524429335266085807578648177642868243826848888597812426992184279452491710080076482932823894976828101937270598043252457793739582005204993887862272198416095396225365062250587964761907297125508909788385379380878384431928753096726708641901414961082771759296578142358550406068025073316126864691295655688362408578, + "Beta": 3007501980853376590268461249011755045018420325235745424151352187417385417580176087271593781440749267211749717129725208694147231985832827427313483774562258792643876131658183075068923868109270407106085332690768539032728172643580795495262506985488442286654580582042532322189104643605010632488554133838269338880534921563420786123289531259354017442570009824702471919373859035918430018935187499611925355139474771036658699291768851098713886459552396091711719614391247748258651557645649989291911069580271980252750231650359406526080545479957694383214254305862466845146695916828277476633940397032033875557157312839479146859724, + "P": 72807529977190622812111998404283915725671404684164734322687854011371539771483354907865665882239352935309380084354755280195062923379514525391393574447405248866262694251938815104791759608859502922495932111471572677656401917709164954182913064633625238386366421281490629398851232848933204546972919964407143875229, + "Q": 84779771394806877732702277930972788620750235013529476621786124820270993976511995986813920523380030763492841035591935276311034101557648552697557026840922591305649438050982047921432149368543932057261123174101064295425906153139403839536605528207579311500361760838733230516785449243303229586986458609161807402273 + }, + { + "PaillierSK": { + "N": 24446348958358540933248892204231293629430849569775321492954589875502787329006383780346609926715950068850122750077895664231719644540231029955060972678061159502087135740574647662963171137617718829364615778022290492645582587279104101911166383276539612474572134721162760124152666225326650904020261799761489967084157096256286347621448364048156406286218833053477147756679860067779179759745245826674762509418942599527364001630285299217025001182197732096255633530993347915904386564790679893178767381280788246412141078510405759121831861042869870662373340077665624605061188310978264737992118614921559304100485110454074852253981, + "LambdaN": 12223174479179270466624446102115646814715424784887660746477294937751393664503191890173304963357975034425061375038947832115859822270115514977530486339030579751043567870287323831481585568808859414682307889011145246322791293639552050955583191638269806237286067360581380062076333112663325452010130899880744983541922077349304899367546679839260088287366342944198764729161722830000671431571910151308988604450670327427104895146418969113051819947840932776708474092765707847628029251643745045837098326120812911440937280017136460785900255330016629574968338058182808646517796473335267816244858691787214624450445754847235042903982, + "PhiN": 24446348958358540933248892204231293629430849569775321492954589875502787329006383780346609926715950068850122750077895664231719644540231029955060972678061159502087135740574647662963171137617718829364615778022290492645582587279104101911166383276539612474572134721162760124152666225326650904020261799761489967083844154698609798735093359678520176574732685888397529458323445660001342863143820302617977208901340654854209790292837938226103639895681865553416948185531415695256058503287490091674196652241625822881874560034272921571800510660033259149936676116365617293035592946670535632489717383574429248900891509694470085807964, + "P": 150408133219598354630657923684747751213361363460938193059899227316982034301377397241147721780537849325010949808630771187159952104604518406032110468806501590181439531197926341855902990828374491150219945706606663472995278171110259885875766878761792023849555971272104986653567803552370930076610562860579329448519, + "Q": 162533424456950531724346445951481960272785801618680105296515180460854862300048126815637578737064095348143261528816589803761409181911348136806574876655430630466888530305263459648667738210787932380046572769526174077036072211726351626560897082538215288176039393035624118848833427794759125122983037899025436997499 + }, + "NTildei": 23594865847143620698431849598652734031947325938269168501535241672231316471436506192178894287593981411822739465296092958039241855846865917706058408741695718295155529017343593105380102127965392668599843706493601662605927544268246191675338929241875873425149736481150041453984894967765570932541937316734795256805454665076684149731128455391428943703544430139217171775637772488742365991100577966899574155673332017572750544263471810692774156040315257721658998854768026373497649100127316232490713691375250228410286087702859305265344887783764559697324849528969194115449021859484423495264955872044489721484314433485237296464477, + "H1i": 21761638393100520002380867002075617480056716039003321164752481845383333676921197500890354010535163461417886378451063439115951658364558284509721027792276613040229310218452290840862255062521213648670548418173760894037593232052576651461197003616437227101916097660732274988528632663146154478630334268454519590378432647716629228622223889244145412218183912931421115084382819610937486710549711697725643148543374949674442120250056116756965863579661800365688527940723567913614084494152684984049849783279451503874582963026369439679316159011935637298226304431210838721968960212103948009834278581311752310411260756323265543106933, + "H2i": 7135111567549056816820503534833302685006550483473151514476328649643676099818626327402227364904052977232419350406058069216384475214090805930135153273382731546034480129140504607756634754176505956071904750602726945717476751729257975675736885218961423622664338510704378271011712126481502667090086268388022192922650962294631087728736038078068549780920061967792495061053676862518434387942293855453359738534200403928177463803071373562027981426465735237689098386904966566112359247683567337666435367250588598888215950455214135029933140334355879189602575223516329252718471101838764682868240170436769936980542710980558835062981, + "Alpha": 1542201682758250256508424581919305350008520179127587007271753702409393945623376785500348014925936356016488326541181238986277483221360914838216386429811244246214224731563106081484472010176182721063818289066935930784251616219523310750865702718466847536245052643453365319767007155589060205742447389861818801109469493808287375314591046727013475023345328766312840014783444091075131167823296396591733202559889923720213752305180642420777550637770088348225690499135023428227062255875497548910406135246099241338072389354110266745936310435346897550640968861805019519655820687236938657762882822942057850209802038125865939969895, + "Beta": 3036922711418111568807093809410413711617237695255235976809538967342514884121134832427798061240256939726176216769004146042760264478982816072550472021614150192219299997959700093608526860664848158705149100237576886017088503542677383500231881664786248499938946530684266573739820068674615055269032916732689111241394657027520556881766811192030653019705158245785037190648119005179603353251487926485976138207938818472699597004819951374049912981114612170037439130073812581119438254039337993028349646688570531496247206163618182761049388348119995465287817393440520089592848831087420574577650631954689915099342668061271213448873, + "P": 85587897660528566147647775910126611992257007204124894087376666667208665206404122496767803940736831384240838251802210305813602249622305895886830059313351132998773444569222642296874858312521697619286938325270518595979588614967458300835799491581212972715554869854013643384741166958918645824828514641021019513891, + "Q": 68919983117032161070561374452873635944847855046385190663363814765019775789510011590015382097781220449448076489850755618971771796410551855305560910516075192153534557522848286577582541268461062710114655529023528797385334610416666375708614934874680883123670782903403369619755028911832782094410453383938316430109 + }, + { + "PaillierSK": { + "N": 26275932419800325725321287711032330083159318299322200419418489552278075536885948479144461869203208673371972722936567107114938849290734914134620203140813435649862317655046358775568541074968049558199274373884746873920118585247212227630388090731098890947073704482538015403857760016534088528781787627104309636611393403349487528994912588228130753177447950797764837232034935078396255687740991637757730417084339982872936535073504809902155931687250349241623210536639715485824021896869337148492293278176213303328444245491544827951149078771403814667394562293990257891152555056676168088576622650069514802804198471565761996153373, + "LambdaN": 13137966209900162862660643855516165041579659149661100209709244776139037768442974239572230934601604336685986361468283553557469424645367457067310101570406717824931158827523179387784270537484024779099637186942373436960059292623606113815194045365549445473536852241269007701928880008267044264390893813552154818305534148055948276127788136292954606947757843247270488805144658776288899729358664946566967290328393223143041896165501508430149565944779203300263932734473914395377068113912317002606017166693890843374089234200543756034186797373517640088086736071046488623723764339589443346251656500040332623883818296206627994419934, + "PhiN": 26275932419800325725321287711032330083159318299322200419418489552278075536885948479144461869203208673371972722936567107114938849290734914134620203140813435649862317655046358775568541074968049558199274373884746873920118585247212227630388090731098890947073704482538015403857760016534088528781787627104309636611068296111896552255576272585909213895515686494540977610289317552577799458717329893133934580656786446286083792331003016860299131889558406600527865468947828790754136227824634005212034333387781686748178468401087512068373594747035280176173472142092977247447528679178886692503313000080665247767636592413255988839868, + "P": 174708723225670121111220164499829879021039540964800372069890553819522977019070694562150781436817531662764109002871811801839731649976111725377161349287610854753665860497151284732375628943046197749093610504493674709196224087344694786870330500761588850210037209278609218355504091456827137711462369891759289445059, + "Q": 150398514365306618225095477721709402911224762259059249675726971998933252004591050061645054990736004924088633739629981240017068147715830915718183718404275840316219808547551858547883315845385418831172166585963641173579259937023839704350759651135691793494989168218672177717805558532022417325099509260746717868447 + }, + "NTildei": 25893715569752446863155646949884217876550635510357076461318744402864301578364237838002781636754933899141088608185660481913514478493973089419035779927383006730499751542223233718263423410614620654385461270337072540799377570377566768816023560597454346957082046999298593220880555163074731128235450531940687629797064005813372931694396267560632978996285622117964614499764405369457978297561765552885444196446528195043018761767407186651350878444155564237515569056173076789385937874887401404111746294147560727568165244598725909477275491372022684510481129154686103582575786169314141369972271676118236722589890477706590881860157, + "H1i": 10766457499606649093961383625737172820829265159778091673356956175583892967708344957306778758109297736814864766494719583532896269669690604203720761720681481841577096555834855336373179101841947503558091014313668078471795844279870577456536834863984179419139359855387399631499068593811712439270160360562675636565805019487999050331836935787661287070284307782537513446216558248545527963220723648909990106237199302557899089960883486907799617601022106284255596257773390438508639262094316323896275842660235880773792657022114968806788989319670364099274825612130059411029425088052542305202787626581670901864049773922023319037474, + "H2i": 9325616643891581826617819705396778390028767082876786273727954466988193819719384830931762518283435276542699503970122515071070882122172378308857660415665458026994975487175196426725892244464316161025857224271432922765820849173429297833462425973753258422098474864293626254011986619475482611502223548565591702144314799462795659062729518239023929692055707637957435350256032576569408119366068811529558260398964299863273092680369125246631691960383613574438161162155447272470532939312425773334967865631206263411126958925534177427869225267695445753342130654559605974957587508553278721992240445269257048113024672077713615461572, + "Alpha": 25723711511941052404007682955383903425161057133881747035201586053447973749350548499921641923234255289498225619500779964906973374039088591245379935798811100552827370660491329925566861397508691323802606492511347628034124541699382369148096112330167999223517908418548245998783833327124297316540768669018046444379380868935997021081756560527451831684575319633694219750299302310910017709590331564627305064219966617353126822667146951527215413078932708087277118565866330440187355789441512352980691198450711650669752862310289485848426484354200360720020179321259631486856838135446828039085530997176642632030760001565994789423082, + "Beta": 2630782297903628421981057315446985117053562528592811893829982938570737019107399882986833363138313781917607777193673435118420565165495725847480413368354756560922867864356375976992639034228042110692174433402892808418538643634314131325729066781811077221027963113337565634414984719325358987194753311293306185205971611865424594023108044560268457021318920830302415265327772143148318450570868965974472018334534449335889237260556682639453039693052221964040523406895280884257744585847438286231862758573146973184078760688540834817926095383491026779005655430836213890806854001837072779499300490541943564237219613499895792016801, + "P": 79399114077951257137447711758318205841277502966383268898995118468042337895570427864986140929621985406538165683398564098633208727274907053456975703789873599626127665278581533934411139319426463417258479572901154652663504341562676189871552156534996663452632478568954382128857474270487923176357168621959682317039, + "Q": 81530240829673829211708443110231526785832088428521573563715778303835602286638924221537841202639800671211140804891220624602525292729796158167755631587862598192662999816802113450156424001501311949311898694010174468044339929961553529931451035564400833535644609837879459240628218537171375078825183313934254200241 + }, + { + "PaillierSK": { + "N": 23665369611627362908732568144764556215489314749845523806293965809454941245759453482427935224497121599171064949930402989236975795657817266655814970360387297719252966105768008199918495293797980322372663590910417824500582200818925844066759529573527102896522216018479611524463926836702497881476175905115686529062276101777201608912573636516771787169439411125263821172827636636434492107275116762256619484395356511675401527216514026803036791338468181318698968729328380190206734483866757121169217351782551271319044093978854862649811761464671176786142895543416434394422833604774898794883904097245435901695324366352007260558697, + "LambdaN": 11832684805813681454366284072382278107744657374922761903146982904727470622879726741213967612248560799585532474965201494618487897828908633327907485180193648859626483052884004099959247646898990161186331795455208912250291100409462922033379764786763551448261108009239805762231963418351248940738087952557843264530983098246544220937385647341998561329142531618709841966805440756788071146869909686956526656627298977532218135748832408768532517549436904820752515944012307914703849314090112103646734905236257962850562874191243993334594058994452490383213585447164182903093422581740300481413255126332613933234428764276730190490218, + "PhiN": 23665369611627362908732568144764556215489314749845523806293965809454941245759453482427935224497121599171064949930402989236975795657817266655814970360387297719252966105768008199918495293797980322372663590910417824500582200818925844066759529573527102896522216018479611524463926836702497881476175905115686529061966196493088441874771294683997122658285063237419683933610881513576142293739819373913053313254597955064436271497664817537065035098873809641505031888024615829407698628180224207293469810472515925701125748382487986669188117988904980766427170894328365806186845163480600962826510252665227866468857528553460380980436, + "P": 173525516596846062473378730183929385906080422964961997531350184546419036191133665431821519012498809675966825635514785689824945110119725186373093340355339521126843284875665594450912600355561598568992730022380887342654322561459427260504748537884363550431761532522694667212749700255677910440030596419147318491223, + "Q": 136379767516320975328963102590735125248267464879175241685404938311930777344163722911744652128259746934998430083334423576146811129474646490820843500948424839672192570810867319424834940954473747048925615573985988637969320914306768759210976111203705037804226908771603164844644144324530124786436241379399561087039 + }, + "NTildei": 23234473896261302165781450598651485869817436767229553675429184637373528970473076207655097233118294288973363520067769057485777047995877946480906034974429206475058980073546561210463834756096789947510964506899961040038180528029714602778999398342901044429136328292232544761810775009777049496802939896686028209172328622072044936100145625047620955467486428072087463747205989849648402038666785855373636595779635309472560185318929384969074978420224809658546729085566649263346259133493818640795032713504094960659201162614900616178042353399554377906277433864964110692390073736553468996997439427166903011218852401195657389201113, + "H1i": 15457417888032451988803342237696904834222464452698904871630274288464624435733580090785858027300388664239046281462735772688041145660446438938257591378536022553149792742416697548175969071681468913921012429645355604159684350400407270612483807941426310338074574758009191125772474240428543496332233333565976361839403936750602594697843798386585448201728051069752197401736407048541808092339307739625762276210478596269673264849579609250711632376299174602749903716500502678629701060559136261566658612505799381195823158832067449408242645440151273350343691563268997736130962134200201072408531133525342066279097238383826824055227, + "H2i": 20536896210685043479047981067986237139158819353163071305862531754675470583480485457565343066081834517813833380010948719674168291603861513281945851969438750561422092190428387598020351907180239321196788968941855117801289176124776001851068578972590507601553597598245570933968468425201812861042667699731656062374652140270446008890490763005197010783222621514965230967686854570050202953811628968681342178730854459492177442571396738987907308396016377363011181812618078462158576765133322205164116430929727002981100456720608253523557836102186011859663049076458588668880051392341647660874837736220825298554047830081976527124815, + "Alpha": 9885052023094509719500572467577234652639013383084923823306015065052968388891527580303354848495219872382113546214731764707666474374407271656598078291009494172835609599698833359917929261828225480744074962667279744252624254123502150453025179928783563337373846083938624672620757871848044918662182907030124259044153871439287158504818873854189929058453612598425601210309601450529531111573922212039507829437170513551308736499982676847784112605141005762280437478129152183505467387497730223477445282158238102170445983894543709147362592936500075360128222832718713743878230136378250701477331368637155091721395373499732354003713, + "Beta": 1687590103006749404632167045941275708311151204219304805970489702723915069037838774538999240050580898673024658981167981563864504623515279492983500446205994252029048516529313023786603127083841606575531777211195028586394470691567713750408525734072721396069675178759839009389858194827406587066060583285018146771617823763639210144824067733403477254474629496632137476625863296969458977772886466045936782811068491399506212972303850793828842590504850804031640597596742838343708928899133267208314733126649080827829842095825057662258951672777725288212244736303268870221469881478523816829653887910197171121940306300734943680917, + "P": 82410631527755025022003297556584693393547181314918641503755358750592755382147096993621087644425600997856363510172255295905511792067851516587309063385404775730186780466396998045019076522997082370258042426732271283373745547031276536085530377359412702466744293674985811059536360741286322834507968685675614581653, + "Q": 70483848580981260414599979725474475816811027405734951190583520125925892804926197700162480292006791291779524336363957746718899692348645139089790596699117213115483251143068385393822216980400104842470936289027715740070757818234675594987508745043208389523829496972816051998813427130515984266040402845645082369029 + }, + { + "PaillierSK": { + "N": 23605299533484155244338286226577800811991453640786012408382045147611586726118629880966186041518833251119937619678342493017764407775044505029508598506144969378895614486904568021623865142071919791145269343730130541198320218014706337044922330526209422402749430365525249308253651979155198544492389747229332804807718659556687287532154709038018125669360367339491103115658343881200113414691992287988239849866170143285168766593472634687807169184215150392153950031172934194797534287436969468929191992469923177262643288497799740743571159182635342229616101290327441278308010140920443654126334073746984701003397260901408349645293, + "LambdaN": 11802649766742077622169143113288900405995726820393006204191022573805793363059314940483093020759416625559968809839171246508882203887522252514754299253072484689447807243452284010811932571035959895572634671865065270599160109007353168522461165263104711201374715182762624654126825989577599272246194873614666402403705280231451762640628187190060745068711870247100608407333167343217731717196438110085433873874074094556820704431236665380306322516217621555563201320069564347065626143580316887640038240506985257200456513129289637147561282389188623646397211446852139381104307239594400047371137002525735946306057621032596285673214, + "PhiN": 23605299533484155244338286226577800811991453640786012408382045147611586726118629880966186041518833251119937619678342493017764407775044505029508598506144969378895614486904568021623865142071919791145269343730130541198320218014706337044922330526209422402749430365525249308253651979155198544492389747229332804807410560462903525281256374380121490137423740494201216814666334686435463434392876220170867747748148189113641408862473330760612645032435243111126402640139128694131252287160633775280076481013970514400913026258579274295122564778377247292794422893704278762208614479188800094742274005051471892612115242065192571346428, + "P": 165272887041307519535595908197672701503927820109112754878317887703657935839901272657370059254536162325630989759229397654992133210992970535629910907642930357898566040806004315333984868653793092737106656851585949433509530330249496623963131537280573325501657769767851909891587157180148352278899887290683924303947, + "Q": 142826206742454731362738749698962830432699025180773546113691307060992044459214795160002042863485791845896367971769906272202390940786936745397636483390875142767715959470331378315130642802159570124623605387634517014939064074008598312858546859342589190597737891963791649492472911515364456112382131545531853994919 + }, + "NTildei": 22345446528066663305590020438361913830694151870849022364405778821403881805016817614773601522607401670101173331296406088201630739075972244938306585480235067979318720678592951382957083282742166305712987511722344100552146703908443126857798655801708464324652393170640537039087336377009467035774524290464199613910708835732417589152467403637726133162330343192846799275019180938514817375094770419093405226781641173387954094919190200362412935439126664429100847345694712305693794439060746896586818064543258581299843911327656738967883335526593424709209402875902534266609083424294161078203488297949208759548160990312530147195357, + "H1i": 5017551238060941620161398362367310820342435895108008063829242496081960489390009519712419683049479415235299382189656190150098434288448544357180020411932136173754450798543877149788025124536075432097498614094657125462583764591061881419260242533111390070571345681806011311832166680240992763377389748422694930389299737898552264064874510689979030486100782999321194713547322661334202113311144982978458850501102699741540233653707348624458278835330143908724914585619517836769426525932210085124745758253522228231988635823659734688777438145455234049010122546343276632365087123869434925507702530657418380104526837699123708364353, + "H2i": 22093615129433862132749253663843116354159921680431569483911893447145303107098695872706218635667106625473745781337903026226532120794708743653641823201138665524543902729621925430961503560204417872411811266068552840723774619976635714842827412584916122073036453721886386568551121157734535494439808211883154573683146465939190422294083752501019200025674010745893658153256356647874232256965351567592260109463200650066826893090980306960741604867379127316987200714889409843335226096650710614125235356821468615644935713198604625775429224768770399958609592597630260321863074432630889822248144274365901992060896696544188244958, + "Alpha": 8719753698677177664958360507623541756985933971090617698811929864809913645904665558240161041050000380202981992209515666219487970014853090270538446209151616794050619732969599130736527973984871343192953309343919027977423861390115171498456042533099158004367690539598553330482379638011785366837735470722753828800317558402368396879066137686424435646437305663923103715807736907889110716163195685817173939035669684400113983929641286093385295743226578212516249806768941223167670419568769046252963282744889502594605217336804953701250452964134192951573698348010812475903320235238525548770076175223724622404961350866298781017651, + "Beta": 2677202772855124717159163401971862890741102401546816760228572452578250224699468540756568870066403987735042071761823738555598434788541389473268728023137189386734463199838246587800384512920141051506741633231801152276871678209113343483068064547702429326271221691319903653994287682969151512930485430332324327204872748803037955582953752682898574762597261908804143515400918051075212574830584444357163742841111429244272936772893213187705020799106910249082224101152156056142124243651705489680787344798758540866575078882105950221883907971182140951091252591158272710895260158175478095383297027890130762282029303994310728888580, + "P": 74017428988003126107595147201751438475076725830250308115086839296805471317102064843831557924407629615142443869214395693962361935639167250542084248858983795342122330809150633707195869080686462423976257531684311459131210587802457080948753006387571126495832007164539888671883882998361202250095633346639254912501, + "Q": 75473597345864486267984030574045027056835325811868301349771779882869344517425552444935271382999721000666898635027368905902168279536374460393970922836286428463556663805025812341867136924991112647412962214567492753548056094170955529840361277778060057304125967140909934736007013681951465140137073232395329670059 + }, + { + "PaillierSK": { + "N": 23519991687887701332483485212941351103217106395045090121159203071468603153822147895833054013278812468662618639277867039268525685116918353168833114455541039622831274814090267992962472428445580157088631702602755255123150585956221863265865091861877127611219468017567962974175994893137868462555608016931588814824454510762809902006813315301878498266313024224232240156817190923591204163450700124518989500699603676943363531988472305121479434251601403064594823495673188630324298756294227620618619760265068702217432544661556683914461696312909230442658830472935970752375913084470270327616304557630238053976366797631521385112429, + "LambdaN": 11759995843943850666241742606470675551608553197522545060579601535734301576911073947916527006639406234331309319638933519634262842558459176584416557227770519811415637407045133996481236214222790078544315851301377627561575292978110931632932545930938563805609734008783981487087997446568934231277804008465794407412073209054169823408315051267837264572895419044620587627558514495197100510274074698430570061055806951627730003639859659387188536171975701561605515930578338319254604822247716649498062014275903480892238278301684220844533157282005631077744993614862474890267702069290360699821831896609812515596191997747867981898942, + "PhiN": 23519991687887701332483485212941351103217106395045090121159203071468603153822147895833054013278812468662618639277867039268525685116918353168833114455541039622831274814090267992962472428445580157088631702602755255123150585956221863265865091861877127611219468017567962974175994893137868462555608016931588814824146418108339646816630102535674529145790838089241175255117028990394201020548149396861140122111613903255460007279719318774377072343951403123211031861156676638509209644495433298996124028551806961784476556603368441689066314564011262155489987229724949780535404138580721399643663793219625031192383995495735963797884, + "P": 168547335708482561144551135869093837739054431803058798524973270409259389557131505015513142607548308513767344468208791815681457966214171751332692533794578884483540326434255649951700778202091721333497674355602440338575049775603934993505576108130741150326430648954392522237844869246469248898843653010263280686983, + "Q": 139545318761772629038661630334875282783131703188006103175188662787743753345419222642336235980441465174136180240544194531420903941435828190051099100721933107331548785364538671670794953511170019099458313702585801886820331973294033293663267135080279821514078296935156405734795895164143773885139149125522140627563 + }, + "NTildei": 23752607312317800056362777847429586586921934965903783538269968851445616919794832691954062544853396063269938947091266796943492604208315473021992303904065746812579797961426123723666901556913799224493989764184606706048526121744613316103407705482374250189302139791762394410814345063076952522461448964626875123530080992136671889650794854115289204612574066425304884357348500989397631732599689037033029455663151918873061228936249578300522495130444902421065605104269052058140865483664519378764485446150946745000181415842754765654980626614175584236009081575641060684092876723057655955223685340540943070565366515546839538986057, + "H1i": 7491723232425967200466868459264536494900588988193440527530226869819360270332011979991733692351798003600627035354959001519989402860787054379799610711252333503801031432778770600011120081761844496405602874774910142311423608813344500878151063311952027254429660919660059557375675640240561237014858184073140405212194209562182906618057780864581267429359413661080307597796455557988590790113332615108669244722249523630702631245914227945061703129004990462006687613779413760265228924567073430342283698794652997369817686027125879842998289832150069770740732790185770634553359140268340820710214444628176259663481586168901214450272, + "H2i": 13880240367748458105648505461444668192418847361140511480466250465492737992773231947830130447663826937534494930092489919101190235549931740627074313797012775279181213542720706165003743741026003879202170770679272163657566238133517932344532221439081327284499103347464379887534601213106248767760584354712932836020316281834789739243486809530526975225101638007173688201937417077447028052125177972087881973260875156401361398086088392265298731287684194771160853015337934166362115801609893974745991349966975191843798553664280407899191951487614351471674266626378551554522052007107259019359108766934182366812598858516458080783302, + "Alpha": 22168273458504136402593077977543796661581841680459347336422202487005823956344453269268585654089899511222355545946704448185960764032021312208679571332738496666601837502577012581928917590240724850857159689970088877395052692996405004998118810916356709035991898711068980279002380531064490521268476355904683132957704573602528219904770911851615611433259388512474624718507073086406340122594863025820082408998363226194766382211931639738429930709513109395876211470261991253908360236389585108244338854350091118569996676068705037869944020755892240480493703977003545914960269029622673761603584928408380459368774828449620821852556, + "Beta": 4368867011820733495292643323120162607067142902994592269630989895866101065889455493250636687860845892389952241270929348845444748610841525223386956863675405360914994830404017671786256015316531337113024092592656865666028675494346836459492272431734202450582639067792761859470087309265307057936607407666920372571532899964051207813438053885592804051908931107306247966267874564522967429321631595369663346343110132788433093418119234916191539313997500008255485465124906099739726702228980434840617517432004004059554082592786454793279236026429174252359015308115324473101916234745466044399771165683071172662738721277190551063983, + "P": 70560270104645717129261253522856354403121841408203470049544843636739277054893923762201273412248144059037797094957217385880994511959739994667762834605861120714229507270900604745250092770816965357578384243948962235254396626158795455007163096063295094799733487682369588924146781265716124936643282895732881787471, + "Q": 84157158401927371048327490082243310018558718836453559837828209297607844613974557313164807350955785120136284783822293719080627116395294171072326360085444170740432431731131367901568242937107147671287929938799421264256909956565970662584636268814730454964713470832225177295971360120517096844804761191226216863499 + }, + { + "PaillierSK": { + "N": 25495781990306014024960781645994288802199351346925861807323432038740329275016095557393101596261327826469136836955246243873454117912032674276319902843741940198734391215069439605967814947426060993725633899733853266054819460888727552404633858671612502864049799352115124729283272129019149235788533364199538896541061981050630454085097849694474068111521214560863721008651032387204335809176753442741296834330210110627789044084204319358725753095724930426003545446545049505436410761914278742594038186406592654517013678056225577341020707804004643055317681990964349540009426104922479905189923010158186612368542414506154866329461, + "LambdaN": 12747890995153007012480390822997144401099675673462930903661716019370164637508047778696550798130663913234568418477623121936727058956016337138159951421870970099367195607534719802983907473713030496862816949866926633027409730444363776202316929335806251432024899676057562364641636064509574617894266682099769448270371162537016306250887818873035065531905043626076179226490557228108502942506960476966756106696999579548784954935358053200047802365887852489157349374377141500177307077242061517010157563884781583365200683034728224236467441988843001873378103966383868169334751418136247788453191018600753184220954999413479388917062, + "PhiN": 25495781990306014024960781645994288802199351346925861807323432038740329275016095557393101596261327826469136836955246243873454117912032674276319902843741940198734391215069439605967814947426060993725633899733853266054819460888727552404633858671612502864049799352115124729283272129019149235788533364199538896540742325074032612501775637746070131063810087252152358452981114456217005885013920953933512213393999159097569909870716106400095604731775704978314698748754283000354614154484123034020315127769563166730401366069456448472934883977686003746756207932767736338669502836272495576906382037201506368441909998826958777834124, + "P": 152813442456605163204753386653603891007807013302559493809303799524947127244864055467400290767135454552144167379199494047408876827037731711410903803773017136732162216105271373319070437864346599049134390648289401464308054828044175432066481266969906788384175272925073986320668124505496029631515291485286249403379, + "Q": 166842534141236420117458561750333156703320295408803061860614131462382796917968433340384330169075496978074966834288718911221271536911493736277942894017749368349634391324884335254652620772682888737477921338479727403777768998274463876494992791226706412955747995724910341962872848451184214295117124193909839091959 + }, + "NTildei": 27415250331439201755743485028462569106153335074612976047453958811717811566256174921188491229617969167569771837519918949449177563677215485730349487915680241556609324457138761947946437627108997661201144534711314751660659875397909742251031805021328014598784460051678374456674011232844117466534805457977092660323315396273639699301754945481647236098770542729658091427401047182184163029694792191957406463856149151722764754927646064069291566262548543437863282404208538450079883482415721423006522374247471493211567893683253884579121161470824129847771011214298485118550937250536144687420719018058729442732372436291938146461689, + "H1i": 12389568868031150844446625276958532410431922576162847272797098032828635835653563564200262468658613327631068452989459653525176166266124777013644115661451664269756657825471174400526423852872233295697445457679114931207886703623413552232141906410948477205902433769290314251112453515675860598629149627222595838831909092498056447047166005393475010327279797496085786340357341895902455478787266157172870012367227312110797498247748932753549892127159176162005107651986248205833886024345475953806587884671116953432417110717752616684348026302180180919695810308952011949471663450224092005619526174751186101703279485508140784974084, + "H2i": 8080438091196915708010273625126799516193892164570746428941442417491502969647586922298641876549466054202737918895713640981952060104739457120809840346905054699422530379063996827683243872458278628850590442273715922423752071881453793110457323319229353884596727603707984741837030689848683177674680686266702950454467123740599346043262441376915978322643912376728418509124688350108418485512193405209224166767966874353185484946925055228132945374862802837314187902976815185162487925453227657738122634939448809110872740263430459201824835710620959870924428471484736061263760917508454626508751323325398162583861933330547034674177, + "Alpha": 14753092287360453203671418862396028709257509800963258634845705676517049176273269126767558360475372868949589642902968745479893090391246301215856179935812783721056914420687014492092410966886519762441712825321176344896287308768866972848204915155577203875224199987923707219707050571724024731473362351852396486434138061676246560869279196457758564598413764827150874520410956396151683468288716459631529431060783615219162944499729911635862213789323871628046319487430508708942067651170491586439774134240773804838732257499779938072943175007572576587727699879688082598982347615151669795112046872183687908878721425381723835211022, + "Beta": 2379190442956496136543945686899123520038513774541641559574073284364131461032194007237091503433568368001797935194111603021324229178734241662176241332115385532525150907464545836746140900608871864757726352426250187582299722858838311530789056760015285620596176209504377945293346670198064021526093003506569907582368512572527007203861177923411794710732170483093733075776621507090359411721000832848880512053342883140179743535891066343922254576715809529375224633198595361634459457927135252363776038502542152114414125499264193059976633852503177673215262124411794218921875352199919808883625775002714687847999506074038224817436, + "P": 82228667676433269128841834978664933496110543612750182971878634104668502491490449886336640641812408795079804671993153362327788914948141848345822098359172199671503903068524643530343427383165417210339060731363080737087926716910987198691854757940128316987829636414239404783326706213428544992702900433867148410843, + "Q": 83350646149701665234240757805177117473591900627143601134872639828965713596017456255984499356426137696373141978929366771724605940978245060817820153691748542914220173785490922190893752471654501796817524901332886154176220505160118142910353469414751074609083908554793702672584240053997908024327225220104381307623 + }, + { + "PaillierSK": { + "N": 20598586411409997058827289088639636850018143644959177174089361161973478822977151641954313789200008369549641775145253816541784456991901183791693252700321642812274688014054467773645216214249448933414549796735250303641086855443942822418895689071194667173147692122739096008404111401138550334231384488714592200190453149684576273049913299299481124548332919804208062970158778597848948434842628364762037556974300970791487149100872870324223820470381650467499400411542109138015531923129762309646441260153889834736275154124505635016052920932631934711137848463878440533416106251712882269879428228509878259479755874088211111894477, + "LambdaN": 10299293205704998529413644544319818425009071822479588587044680580986739411488575820977156894600004184774820887572626908270892228495950591895846626350160821406137344007027233886822608107124724466707274898367625151820543427721971411209447844535597333586573846061369548004202055700569275167115692244357296100095082819397050462431838732462623587316497584295736731680169960595375182078836681038025298976873709619770602672512723663868095696723116744080914699168921624583324965459114922099830062093700103572554511204975232571109762695934024197632712391168881360476728631936284299182518329774668635987724092999115825574278078, + "PhiN": 20598586411409997058827289088639636850018143644959177174089361161973478822977151641954313789200008369549641775145253816541784456991901183791693252700321642812274688014054467773645216214249448933414549796735250303641086855443942822418895689071194667173147692122739096008404111401138550334231384488714592200190165638794100924863677464925247174632995168591473463360339921190750364157673362076050597953747419239541205345025447327736191393446233488161829398337843249166649930918229844199660124187400207145109022409950465142219525391868048395265424782337762720953457263872568598365036659549337271975448185998231651148556156, + "P": 135567550265709806866632234166134269740170500411618336479700898978018633731364072943668984907404057419405714545749036353917924033489948202901628630468181397408654230225746695477209516428505817326600448345195121066962979120693565634441417894886219736532222975637728477989271655548383460747820267430558418742199, + "Q": 151943340209638379369202140067815645597580712322981273339156508120565643437902215767770618319477673830876089529676506234114502990658214102768373443230678573956946774674171414509107556325176872300652295828845371729564549943889973811271648231229499843426619403506555426853497023624222823283749608426001544596123 + }, + "NTildei": 23709398117609740687245066676544324649148256630191005667215732190931355931645437299269823194548941682189597123449629306330371331589565301977978456941145569351940318683189222038052227925579569364328120915198872472961681209822356771715012218821247762707133376310268539928333011473382903415292537633076451163502807766802745976613569326621924391697296018762063650437559148565533611545139054529954308458903350602508695048688797279476847719163553683924886435425866687510973247377984361273090542645915851736473681494518788487126320678491763295719605806533949261505211880405616915975683532764657908147112805059158763251830113, + "H1i": 23154842234598728637356423108882756759409944773989725877954618967361642797646764344604850469570211674569602932462032601030007095205371745568830747573466773911277837484804944094678431921673065933520295398993579186984532225439189695199497203853671104329925105586210793967037784683510561610031168829173355580026000009039165528315820228635620264342323658880767747469171898172047376181539434376229435254921601213712551114148842471150954920616991307958047755166476462971394086256303440875756463890411341405406050256948647892962533576338910197330641859111993237327806296080164732972739684942365773611542070787550569275942865, + "H2i": 6246443154638431932977863686966805429619529010493551474177014786017190037111527512158290863196473283829829817802716267558383203799846108159451454425618338319270376705962649372123484530043145093070200321850031212881790113704417474876107310819984252272405390083863807765602398058960915633386188205777092249755583351129905083108259724252955712221791600996893747200284679850789906850678080292109625335765398057948802882781361923323372422274892762519118970248415956863525960792283232997805229861798014784868724762511857089038866667921403570426718185254284658222082492086869316531495561633117724392220621347068905119850264, + "Alpha": 2262996998071823209916796986037485154941741789024074161733184681388914283540837560788791550056876295340589820247552694314074109970511832324335943780896008882098802181150467897900766473423906369829097818457564792330676491428552983057456113754503750540854415705621692030377684561319747999076702023699104706300258045062631892603588607313255242615628999176146895774530108976262395476837857723859917379026229117276259046489773145565048393739536062755922852325648683661542926366159749042191105527514872934801929006694744435789752412964217629629680647491777016675052081869691726251715220723766330279742952965287196781015335, + "Beta": 2967518709784895641493819579299630461419643611600975729354231762816373276975368096901858672523874722819799940211602780678175512606098090304823324439639955561014459280639682531502452023158462018663882506213242383631794780179103774528953352267803134736911986392014893325708151153224305294291366910338999085365036368090396190298734571042984303013604799809812945580461078331364844916407714625705241980234634022981793380132461565375637339779439604007771600393586521227127691599882098646009748490220184195688714411662731033863636354058226555797673647315248207419426849740166697203557853961647797262458774395926281997613574, + "P": 84060963277763163222212522191385162909150930357614651429787261859109225083377426145273844277465950374529712912558657719506639775073973407432205797724155819056205120799162366600790111372942864358487685159080258566429321578092370330223390628654348432664382980944832655515586287789944664221635038948349094220859, + "Q": 70512510186406706947866602578837989402596958507128134286801510582666888697243491668056739317612628446117397224842181870175940551349815361357334076307867431962869207393014376183077096686988220813440065695936729483180032897973080164444580148587541576642649239353271643845738002575346762071807591802423949026163 + }, + { + "PaillierSK": { + "N": 22180121464207362735976128116631240978913164658256634812977668514009986171914002392778194459858556528231171960676142254191858664096122376582093924022512243676896835669722784891569271003370255244913874414035025803889939615182987908921400226116592787975592655581286945287448840127040679320960440298144332461890886108587572005327484572769987982130860484859526890540072338948943138376813600197395340581814906867123063488519992543393800757981669993845253295999237545044663021222679710632567249557952421998440072959241109910329714216546421448847785831855952840996716913415204695638850991624728609934727375353316839241878293, + "LambdaN": 11090060732103681367988064058315620489456582329128317406488834257004993085957001196389097229929278264115585980338071127095929332048061188291046962011256121838448417834861392445784635501685127622456937207017512901944969807591493954460700113058296393987796327790643472643724420063520339660480220149072166230945293840909500562935222459298172743249546924821536750013563424492952807182066742426286863877466499606998056888553875849347838204633415146645163230837344526886655329860837748680004000298783456353814046517508125339985567317059177998284098970768926832945521507605746109207829424132439441123473073059830971571339974, + "PhiN": 22180121464207362735976128116631240978913164658256634812977668514009986171914002392778194459858556528231171960676142254191858664096122376582093924022512243676896835669722784891569271003370255244913874414035025803889939615182987908921400226116592787975592655581286945287448840127040679320960440298144332461890587681819001125870444918596345486499093849643073500027126848985905614364133484852573727754932999213996113777107751698695676409266830293290326461674689053773310659721675497360008000597566912707628093035016250679971134634118355996568197941537853665891043015211492218415658848264878882246946146119661943142679948, + "P": 158406456987586110787886654267129469694241589989327225986077758562131243821117010977426417711692214356070356641962465786869009675668517856670824628913723814272693782477807087449572584586998612779437210248149532980957092741330744520847193152994323980542562267142681254011405979330373609553385720648494650325479, + "Q": 140020311583293346251767519375366162072393626464063286959412204475392768858998333844186409170215438770879354770278378911255339039171182698256009695634767457079667718526406185109676375798510678032542713976709697377622489686734707758740697165104851125131335936569795969180737380519354078227843513006401448872867 + }, + "NTildei": 22556817737084427348196388262609356867827228024520595255229161722345685573789035752740015552861824262167086825730538229192851160092243455559033560007330875073405327131477123078815866591383596034828157289451473898593323654418853552601563671973874752115864526023247741570733889440535086361376204319182923580088587792185291987271475553247570945680249422851893189440556982785070109100536372514053693514435056908399147243294076299851642357190701013153546535490792812905395928676043661254762240114180831251433054772376368714065309219019149522579682825460670538347031220659996707445257639906546326828992748175042561601918093, + "H1i": 18572855300591056517759535193408915394441089755465521322925159573477794502147943310519053176263911692533973917283795849377677277142284509135377920159757347497192633442836348458344168680954607364328338929077808343700522619921543421121876475323677061701697073369523549696416364546130618731709563558040901665569599164784276629325445429538931816902003391431220606429358138129077912257321502986049124526504579807481102388878884752642851921427956096807136403622442629475523284644731860939758455489095808318967229502715081426310406408797239917483094707590124746707939787572018807914629332719107776554372045479062804640711914, + "H2i": 20752670524284816675226469414261924951532291432186135305653009607402668180507934579522890244886564759765154882293249097654145029576989225392083876184606333861699117887334181355050132729814591406036195934831554669793714286269468359250315307816120933564533393371520313787712857502636535277195258913400547443505915711268494959312402582342977240152521518974455573375951288519353434498370718545041688271566566821534206931537104363019943811638834396473893058171849857269960293299666915110178235184154551603587572739144411382986477684523767057636261596419827868658746102334546759541137016134664359030208519687163192044340177, + "Alpha": 14828837251805176098620220716504457570210921661876984168323954911756192206907956081241082209579408140854257239347155648232442267740420473239481305155700450036662450851999762990560849654576958954957492106644909366783766207205323577958537338802679487300182110963485948119865847008342241305024698710493370182179717746511122548596832098501471473988442833946878293226951132059925176903228685428338784652503336620719173272056767470509935370574109388474263920152373847705015621284254265562907058415446703106792623435541197206304690603790755097488731315756710230508821026538089264151994813772961624045459892587340036217517135, + "Beta": 16444535290818355249379965906470950381861978238807214294793623507889452860109369297414291706614368553372833698207321850797222387245846410689724471150730679834997576905406885576303743237628727718658665654272723424379133049588886160715612441695717298387742548090558351353642698574929533686118548900175321275335349326292288561890514231284365732638921514822178194173288162820414124204128045360528535480330971676654939628062442218450627666981974507442114279508522170221767616045297539598857857699601356099352010418853395762155999328705747283068446076979742069325947792215379742446997892133279644747170842170014159329803, + "P": 70299507285138192139108808715021139023808736307455843939419262209697268978779401087517925695959638229577275292790135263120822262238591026780814367692874780523897416368966776216236918672264360731726051750549315855856494026067640293471720811477573430536884338043428396952526264968319467530257641920719919220769, + "Q": 80216841512106502669750351468691812667945942084464700022832097164024415028650918707543896315108861841816531301216891020230546407211933468738944671079555949982134687233399952997656991310157599836852495631590618089576695760900678947606804890490977120225500475826877368449272675346436137810085729110165398253943 + }, + { + "PaillierSK": { + "N": 21603530287347385797804794857836116811924010708961974681986292254606032206395063078084914269784406515838470630661815491494131433294315539716816235075321043172426359604190553194680349081899881349781292681592947150484479953308226592623497942686469645528859573877582667773589125094536868989582670938988180517648651804299940377660929140216502528356763729908955619175263914134265555112688605429477642841630156830963107723017458158888251244023568765159476285691090207049628622382509975046458160656252318489112347132674239002207165966567317423315430824905321954352762173443168862079668409413962898856123401984237887467216797, + "LambdaN": 10801765143673692898902397428918058405962005354480987340993146127303016103197531539042457134892203257919235315330907745747065716647157769858408117537660521586213179802095276597340174540949940674890646340796473575242239976654113296311748971343234822764429786938791333886794562547268434494791335469494090258824178810215434528734334091930829344169279713171985945407878163029728406174586092839182982973461535281756600746784460230050828255543704021558198665413105958425266218031593229066401673205486037073775269035689031504630542318836427253206102915949310258760888211773960755328329741319894694104469543289481794908822318, + "PhiN": 21603530287347385797804794857836116811924010708961974681986292254606032206395063078084914269784406515838470630661815491494131433294315539716816235075321043172426359604190553194680349081899881349781292681592947150484479953308226592623497942686469645528859573877582667773589125094536868989582670938988180517648357620430869057468668183861658688338559426343971890815756326059456812349172185678365965946923070563513201493568920460101656511087408043116397330826211916850532436063186458132803346410972074147550538071378063009261084637672854506412205831898620517521776423547921510656659482639789388208939086578963589817644636, + "P": 152793418385986211194606641208820856394736985868073314062376223335453727103296428127935717078405293105881468615082916405418508338319570512028274502222517184419247450554336199169797723706951580371992763565882661345243377592705990508250672391129486212134698734843306676137210677289443117643840571577343312356039, + "Q": 141390450685333981066349713635019161809566579115655045445211851473289036413123322983741177628680974344024760833454782381176224597841151531050680362655773014676938868769180714485016521573292761189816297730293331600837951301756926394974320615571950618851051160404044746871716096884067529540474833696954337216123 + }, + "NTildei": 24280215189850071363732442969893473149533654640543993037419498264798829315861184016029621994684532110632770714560305133074140324779563316088766891492363287225368101347524216156367414666580970535658630901693213395876252523760380814972732910793922766433073316164096905128099825469033099848582124568914000479759799233883707042295229692419583332246124254170248864338315962011455644883846989713761421678251973024708146493617012317170145440645107944080316369336904606702029327874454441085567150865188683236460941137145895474798971826634508600380554895808794641544663523287478817596548099911478298867080564689794833630238649, + "H1i": 9007705317203282306813537888273913658790786260563680463357025650880667076157061544017632072991742635705517702837085699421252050831934233847941646382941769042124751444440200435482490054189032389049391842304482103068717938133493187672442782997357021304454328238492348592669173053317861253291241335099983642473803416704023594953917657968287828895489320408127265881173389713126214495220707106858992481428720389035780537618465868291980464053661422559133490256400088702259166122932444729353335671745747709476607763231380618116626942845798416315747127706781921588045276819468700444715187938079207465641768227341451618973175, + "H2i": 10018925495728749835032133500132969085996214793897478788869524692480971069987118885943699073297366550591751702178264784559084465269631722814454632385108659530970036742364474021716039299345441695477015603133457163661165486191673380805724436021092533260955902834444439897356688899064904827041197573197462340804507378181634974418478707084663057013069718449320872408196414152712179124795348267920449137377601025562878983185800101190680313815602372122409942356655748422431414065664884893248145594412364785581500708112476455973562052013210640237456175622746294070225729579703558302734731179304953968819590147754368499046269, + "Alpha": 8533587849824646882485550002778139810131456591112273634209552440840696849288754856566001937694455935441386474230853894386781044505341834136390769541172112862228107487497014227910850960408902848311968996693735314745112964554161958230286726675024630317834262373306157820192932707152556488428609316895227723008096534541728456563147280140043513537732240714985868385301263763736227417675746416217581695942103832923238982995865486029362365636636939122381002238308958214159125810776260488651660903669334940772373415567342699594825864867047623901615433347440539766335669534882499790340445223015076392464633405697719139706866, + "Beta": 5285044657092695822612417191867227939332028528472245099628244280607194974430695470625539874433342659183246121785319149258216190552049011593528877911887692315744937271823734817912268909093070908503655957246015020775010324764210217537074575500614208923729054859157762753076741991668329894998107945436271746250000364585237817704585629372508998752946740077801560650607026568533384360307527737035787010425614112860224616896616840024803235072305486967570795864550268051789726833679116590455203817417561489475313811291802029258836847342025082721696106248028961297346415507887253086534021307867513020044374348322290220248131, + "P": 71895168506759145745930019704233012497237810169818454575734310215676425599145027286500685575788815411949310830625666315745849129153568747564627757399135978804182195113289752730484094736150841202126250382155613278595153782825533699023641268910984808024384835829734067105224625780425469460722506804142584907291, + "Q": 84429231108789297331600176759701539867920319577881747911081546698259061725043078225772751058326727123314378341576409123774007681314560047557404139447367814406503722904576254648234339075317375652250944512273575171106105525029174603349427669099490784109940345031009794437092983997714515430055437394806547870151 + }, + { + "PaillierSK": { + "N": 26679746203376142677189183939355438985552579038739605620284326252444444356779104986355709587389257322851634963919828093483236080109705859094847532214789215244221326742210657828130096720762360726755570895241728713125547657981476653500220234159784462493060833529738523438624517012847426207766261509978099930577889958962848916786126489836548796112193239981829203502530108500952227217075100834971293766643332548844178440204902920273995947413135797499716873190013238825119433713393453401041678676605651013194869899531513258196966904895665857559254656126634484138551272428558052991877377950855878747245512919870101444237721, + "LambdaN": 13339873101688071338594591969677719492776289519369802810142163126222222178389552493177854793694628661425817481959914046741618040054852929547423766107394607622110663371105328914065048360381180363377785447620864356562773828990738326750110117079892231246530416764869261719312258506423713103883130754989049965288781487918937908293846331039633333468026613252013983363243366766798308598433974650133170685387530224898847392620519218116307861949140487872205737664083241574261335592601890469522071803272323455546828344611667028090024678088411780417091374825377812320831596847282003366280421743512117430290162335618825041814106, + "PhiN": 26679746203376142677189183939355438985552579038739605620284326252444444356779104986355709587389257322851634963919828093483236080109705859094847532214789215244221326742210657828130096720762360726755570895241728713125547657981476653500220234159784462493060833529738523438624517012847426207766261509978099930577562975837875816587692662079266666936053226504027966726486733533596617196867949300266341370775060449797694785241038436232615723898280975744411475328166483148522671185203780939044143606544646911093656689223334056180049356176823560834182749650755624641663193694564006732560843487024234860580324671237650083628212, + "P": 156438563059542254634590142964685511064824152926905642678372423190484840622616774973757608929029941470170213611754161541336609192374104717935866113008958361214690318953876923050636635100568538466896644548352454188494472014808451846270392660698481095207045182112380394591388893171979311249377005673399485772207, + "Q": 170544561913557943799237614317443665075189324874331133365002544165125179584534759731194786939242157576313441352110322500043614322480717037369531748837797315382072209235795538946898434960435563634316565759826747828423076704033844878801513815180378401681033551881665864725145570659664575415811242959051874837303 + }, + "NTildei": 24895138974448941937024853210531763456462828890564049534019635443059125347722550654978030580579892363944633659695442302314092068768238783109304237532459621062213180415653364364321841253104579614893248233456050582250348799433620978658768957274703353520466950534256661259007497367190077831840417624315799058989046938507685357886896885866600662802385578611011751858246917442495462402934714334228075270506234034699272402291208442007227657781817951754149602403826153614658458972540612931574559655547569867664354685784485931046176167121404819408786767285333538123496380672380549823053628999612844450141054219762278621615621, + "H1i": 19102933504264759760777640707421474865294029226840523131481229925336893049795447790488853939024371728910727704259657013279783225772467846849639657760423038789255430963139847073694682924764148155735049442830659429232152750646748738329071834472416748912608003782310765152136964701994801833335660316140832874020011561643433249597845168089461170583352223509205854046936136817629900002806542568501388549596605586341538149563609279101557932868769001857305751119927881102522859900680576180662199916986039040536091631073334889139402568804109467995712235364363634031506398223563446517000728330488102598261020974367628091663644, + "H2i": 2136268006164179473637974840237784865711312948939168565624270289306317677272332894037883869132132884099295054146958694001629038995521922245054741844021893828618426144521232872586694951397711655784738939258376522514433761747378317841097952927719935062645570200471031293887655903573524408986084164256584783111164037671878340168232580586721347809230287490303782297656198886246279977197890638335952941941937586930940966249993979774561077266815413133244689093854266932483969370294540299854136018292551974159545209667801040375622495683903775156536016982062386561257373387154498235287221776891433904204214286436493113832227, + "Alpha": 21685954814990295600866667829478146257999652196166827274670568914124343017165670887558194456470092155633084929698610124848865767387523811360505792494290212299756153192942528193474509488699901312908823998273538675067750889354392013015284035329184430930572856943518513706849220940822269431467488044488759543557140145407601993182404205329555355277362951471605810249452303820848719710614381029444796143357570981945862336756734028082903856498368551889401921693243222030246978685924050474734125945825010956024058586901318503616448227600420459600229576218554236032725738699380713417736570846674687215988534239357788411993991, + "Beta": 5358942530499646602648204704950636936417897175516102024712079673127192576249972219142932594244627360013271111274961619805680660623789727288483946226536972216227454524755458983065091057864985592379272825181990788724195005349510718794200361382346402602119705776837623769971103715465752015731788559633936332963812372540885555778551159931485364311734759663970171820005671155939328536345596154848593511179006369555126958031686727650444380365260234084465469303884438196597629656853221308582889632163176990551374300077027878106197020846114619323574871159621820051340771100680277374573013206813847701261353534338128097877714, + "P": 81354150846056564292048932978157053381328676154177935348880152516615577347412663650641785342372041919738737691029143395893110629977164576717406024057306994747092183295451252713220464758545574410136691083363238039999987239150619603174219278694604043676105504672956399128968357432913697022139730802817906487781, + "Q": 76502362557864711982418973716834515283858179726082247970992494288425007509371388458574946685922053126492368376202311751062484525671750128277438754198108843709875549268436870827444233587134188085180658299608087233702714869084763315288418349162864002962060276009213178552179660223993547389322102151561927584183 + }, + { + "PaillierSK": { + "N": 21572668848287101158145582541636973331672819717877640035371543298202001689901989876877718641586847132552102199649323422026358962787993228112328763590391354803527229216743000246742325566153695294637206035710442172686168382444931267238982042058397242579987290226128872882840659421808834473080731573477258048355223010827211900185751832246214354514115639551426066223124956314893799546788218466250073941665048640348335903750985370601215938340089099869055999166634036243491815801994541107482411778913622549843251726578059001931007802601656512716213979241902270680661740061520368419465768639362751202751759499697267627780873, + "LambdaN": 10786334424143550579072791270818486665836409858938820017685771649101000844950994938438859320793423566276051099824661711013179481393996614056164381795195677401763614608371500123371162783076847647318603017855221086343084191222465633619491021029198621289993645113064436441420329710904417236540365786738629024177464390554939856046924076010718433314853414211689822922602265015276277095856284439731100834541042561414977244842951021504691475925428416248857629193458531307856898750890417771316726439627440118331313176323872299321852620715056301922538243725688397806872894251992615052555569568402155500462165253928494789496714, + "PhiN": 21572668848287101158145582541636973331672819717877640035371543298202001689901989876877718641586847132552102199649323422026358962787993228112328763590391354803527229216743000246742325566153695294637206035710442172686168382444931267238982042058397242579987290226128872882840659421808834473080731573477258048354928781109879712093848152021436866629706828423379645845204530030552554191712568879462201669082085122829954489685902043009382951850856832497715258386917062615713797501780835542633452879254880236662626352647744598643705241430112603845076487451376795613745788503985230105111139136804311000924330507856989578993428, + "P": 138741520499166517923486196498423772625111253264149755480293219689982216505498294793691197228416432447804733438856290237585077764957700004393499281161031378496891314476698757735513422945693838575610199664250749538725624389694680346899380487961680147506034421505051417312983409856133469817573284249199441333407, + "Q": 155488196833021573980194028279064111783699874782270622440133064651263138570151291994181075354547085070576680626227037354247908724274567366947241498555942249281126985737006807113445476713048474605015174266063653748576936781849228524238111302563794919409917136030086897041646092702306732009855707591078607454039 + }, + "NTildei": 26429808408504924242561895137236638981809070027641968896647929083627511789161213341870524261930994441165356000545458602857776828182417444773977126411295175492117036973189397230025979307067010540064389545005929320391155060590724678578651450735786963521641592339439707389691979218284857018124860895147617065363223496354117829387221977217835458133630033217468770289155226110187512924716677834605145638796283332657769718384420532163585836406719340272406401786481545311178683942375802129751606594114717696983059251439304876088255513498250348741165449704002382881649756367690168124108773680242340994794312688462544972932757, + "H1i": 15951820064299531652671525954446619618409163661007005131346039943759266429239527166826313224558710563219932581460846154735534725868792084671640881334025249637192613085005922940018003587636267027790279542794013832225917905097944644586665630294069461527292289892577441749411224348040202357737020225911496695267822276749440270543402482189600733341463076683541107121848727641661705176210274892479212204854628528629424448066635890760054740929368768496186709818647181344418167057032882420789206981152094126567237709796794548519360019680928693876125586257869135126865021661635938703633432803077350477441752739970606091167770, + "H2i": 16074877799791379443338339477056432350755356859966335419491716498431209641542784838942903002638305081992505154986778902464663110555148390923382529611074823246298279129161765179292323318121796692381794604623031262028716915293257362828003094389217910296468743217850408242321959087063786951852156664974715020370152232887627026782606787152485054641107371867975633244530285368007060590319238446320251110873634426659147712499111381887644329626092291901791219246022675427964627739342946100922199909937824384923019085227916722261008740056703770592189465215720999844513270424106771007648546744134972291041158075275913534097871, + "Alpha": 5159324875064837568224001764311508354731256271851917853748196921763502023525317375039852531940781081768032260382020812457397142129710419997265444443271024903733148509086556958809698090602094101330641867200480443997545740108277316916870170093896840432205890273344717931282169500142882681627271062194823779826968639838026515674604429681622111676434878652226021404984152005053202945132912730445863916804538649954815122180991025339611310443693590542290688841743239748555660292434616483604583263006095752564169177192836420886430816620476016759983008226621384526182569123843108047535125152563614766097295109043958037582428, + "Beta": 5440222588854811362722663344362045989657163056385789440794283778128016414852466041723455812749903925518475808409863187114924277351529971566222439099448257541284285288925204145269307015184771743877066097840573100506167203444543886202536114596392724528706705731512926669047788819570849519683198397264032788426404847166295210664000466187053855340689031110788551381947015998559419153892520227788191395094189789767154205872083299139170106531675765410280617417911729259103210496276897462591674685088837686966169903053706687123543184167642295856725601494555147769997013498270280479984051151172823774087857560236966669834552, + "P": 87138008043258510150181007813060679583669439022606797582596960871539675782539187536829747454690351970847934636217088606733676149414381168585144374825212431826491351375704844166034636289428993888235380920950362689515872079143669938641749597229747429877753930318438669533560450084088582053868751577387682204169, + "Q": 75827440292714161713174047881077398036441041692540486028640252596426849315740191760501953274854046820087131707203626747726625453016023944675762898549197017706185838603084161326943365880487739063502054706399403438546325888006575716229075627982683975083873833701718082147685775559945089320678487849730265018331 + }, + { + "PaillierSK": { + "N": 24320605472281769611433603846904641410251488082870329796805181846280621973054310695380239575011046076273673589158518085003917544301614854613194107695663974550748738716413864440033269793937642832002983905632009737493349001249852153713267397616331816153662195064591617922985638917417458082495088061563167739194877271128624293813870394977905723137242189386267772648798736287255799299617048063074365527414645670315139639124044370028475949853750198124885857177343637738690096202695849561098027817486612112487051348894015228005293881560927507739325834694573296053410504812744744978932185131947391113982462143737332207673401, + "LambdaN": 12160302736140884805716801923452320705125744041435164898402590923140310986527155347690119787505523038136836794579259042501958772150807427306597053847831987275374369358206932220016634896968821416001491952816004868746674500624926076856633698808165908076831097532295808961492819458708729041247544030781583869597282564129577271324142604321102367448217654920482230105525889740288516330460112071523049854644158399031816804627532239556561675567006563974816254181985204871223221254132754956502427490743733688942232191830701403586610327969071081929645172472486745276852898945554093242049152892867458639622727180587603215165306, + "PhiN": 24320605472281769611433603846904641410251488082870329796805181846280621973054310695380239575011046076273673589158518085003917544301614854613194107695663974550748738716413864440033269793937642832002983905632009737493349001249852153713267397616331816153662195064591617922985638917417458082495088061563167739194565128259154542648285208642204734896435309840964460211051779480577032660920224143046099709288316798063633609255064479113123351134013127949632508363970409742446442508265509913004854981487467377884464383661402807173220655938142163859290344944973490553705797891108186484098305785734917279245454361175206430330612, + "P": 149932439057994960924305064740211283375084614385842245375029295908366973180270089566395000818853944672450390526483409792202916192694698598260881329388501065295716088315334028787022088771630906918321143206655008419066297797057113637987604114102260906768089389155326731620757322996711115507495430643750945733327, + "Q": 162210430411756204660881270960776957431794930917470192371927510770399665516553830461870817307474927579055639342496481123149682527042371576992467483984726930947937606115005619306150747227513827684265822025957412413006927825728230242047885635497544592936617532481231763213122023215762719229512351918374831609463 + }, + "NTildei": 20421737019311687924562999106255570986318890649934053490153202198211865081159811246800883282987974662848178581319277848263051121977439029573861598624387410326336158432507787395926178703585484381170622357490225439796982051607655131061529532254596777981970254409940494147054860995369370317962263581663938906981789998446225581684462254892810215261711047986307756386623581321127985497814042224466667134606325876740093698403773950878656141043168046918076024722364243348097139312979779653235819776619444385849067012152519377070773434128503176174985969630008212981035761023231748967463304062846950149758844159789331091496853, + "H1i": 10835174848260754098810788937620020798873941388272952131390693269784935850924042428232413169064458938634900009775545221949373070639614170733138662414647192893455325845731726323633631040975422150137628104818066775037822957989833723939300105084023704856532088347132947745384637305211715546182094954966468900998119693477342823214414022291895545763250190731881219681960112265962366101223668032245836759830440528089502455217342288694333473814533422766650317352462617254440440171428586374644600791690496352440286377597734587762838369971728588975473564478914545786569309183886142821856175716217906458612166270976044159947714, + "H2i": 2208437006578861715644555917731149116444276764276141455903371385382430825238652402193233708915610203385047683888719770218409057177232122806639481503289933074608699281831900233975230585785930475955110984026391385041278047601003638455598076264335693536898972276981763680198133707849190802188990380484756762279849048871903633368998043714537385191129881226827500726553354345066046510159079189994452850503266123277634416949510810022509833555330165147833856617800460889011847166283508758899274161605199335334285567918184413066920856009966220610877572639403259893423875848171431199424188401959285740905363534752429074732627, + "Alpha": 1215647205092419098929888575985101595804324977833712103150226387163796354257933615560027705108175137987437993851946030600332740335762579017947945156270755422640946657288641755403861106914882568372871325293394028178410543391694258555846271236947673517154947085603741983390319453808484289997677711556557801026569496666139001758817832915923299672590168661704128371719554454363120447492672095539162284893403531977139629183340241690062160913496368519518627194598552803140599268848091355955899335310996928924340628274508481889468254564933634004969413058125825001465259529036159247415648431503736935688132383025774570259598, + "Beta": 4181053269301689083053944851677419915490476058226968572970333178437894866066239189905225132920421895096236002351182034986152724795315880838835087124156308163412237000269835562973609250885730266411204676629533599226074240814119986578194380500286932084393073422326001977710937639439856289414413588252890611289074412517957844902241527489843772839180880514870780248109464555397213225554749907832196404755266154183598714362342546366560923854834022637912764215233730248007046756811238484195294351279848848646070197358116144676921194611906081081499913815182421592924500587702249436797289796286536617145021123621073235989912, + "P": 73499865680965885339689998922063130692240345179070407326141453955707094343217980206881447911503666177241608913179657075075107416373167796975678038937231839840420445192982172026191738050982539194943138971429287525203030853085572687274758193655791992049864868234703627563328679375922927127499951164366098090803, + "Q": 69461817481253794720776750264645760351536844356812043398624164012103508157664020913530488107697386851747959292005405964197889610837544618586097173032902804027948721720298528468558595198023910401263444093810431679674656807368422314344618268129201118987051008619101144394243496262415829988484541454178303287889 + }, + { + "PaillierSK": { + "N": 22989021704313753198585575790518742216459767102449646109057501184678871593295290493476311413439256513650443915105020001375731006640997294611154042698792519502288888028344433954515370744561086030989667473748685420868118226307189243117558723706712789210737831835103210111650218368550882414313314921922988791930316071081455020693990545050236488789709813326855357767959643562802425623144631305243158037573670908045735598672518942740521468889060714829856970741297932849647247963105055610506429430126060236101033802242530846582215523130240726305208334547534367355695104159217910252226949335967314185733529832335582327360513, + "LambdaN": 11494510852156876599292787895259371108229883551224823054528750592339435796647645246738155706719628256825221957552510000687865503320498647305577021349396259751144444014172216977257685372280543015494833736874342710434059113153594621558779361853356394605368915917551605055825109184275441207156657460961494395965006139688140338151960839213035219596046044526892881080523500274133120559775379760203237402842413544322271102640317237711171852463423652424773173932153967665857249381310309560874651439374390782418664761592801664534799395624638618533269020619295250773574420644326078789816855979528296224185718750224972501683714, + "PhiN": 22989021704313753198585575790518742216459767102449646109057501184678871593295290493476311413439256513650443915105020001375731006640997294611154042698792519502288888028344433954515370744561086030989667473748685420868118226307189243117558723706712789210737831835103210111650218368550882414313314921922988791930012279376280676303921678426070439192092089053785762161047000548266241119550759520406474805684827088644542205280634475422343704926847304849546347864307935331714498762620619121749302878748781564837329523185603329069598791249277237066538041238590501547148841288652157579633711959056592448371437500449945003367428, + "P": 142767417405269832579753188025181284829569054099127393401235641382431194837410381034088699025319690021008624829461731900422413077474110151349874318624467085201940211844436150416855952664598758342126199057309767928073345083833535733116208863862999306030955982356536765924457768755801417253293401159735920927199, + "Q": 161024287769074557489113436140868312788155218970468213511407373153753308756461403802594532863524129380184768562422735417755350884739299828960748558365530432730808988640000338340270598712679912921578079999617749584543386797129953505554084445080866502515306888209215906668779608154920320108798930725901403065887 + }, + "NTildei": 25455578012420121892151731752422772822935400925431363059998387771486286742736814838632932392888651254492034935457440432546282195520483791367270699683777274182424175582995274974920081833168732880809659857274830175421620074360608383488175867565471702757374369110310377589604602563430163524113760933198210022677840368106527071350200491231903635507136989477129549748224914364315074184746721892904640140193483533644542140128031546379957845320802557877307133347327099493769462832767926217368716468615578045658824439683780194987496356236589807164003365736731383370570473416302294510756595212212599613030462794281448139847601, + "H1i": 21125416144048993901608261117681927481355894391887540526441486268517465289362222892244305634499517277762483240237882465840520543311294784862164570259549295701663297371732120229860798993800793078785148872218908014099322020656888057147660748001948789973708107438421182474635563003503220652401802239810140693325438527982489845521148537155767550112328110034045164953610299493388001930589053125325790167356976310066760061816937161070977340525990900060778035351145441723732327110379364720361174440092423248772196897120598048018763248922905251454903543452096890459662795037802836282296982146389516880783723216127927056569944, + "H2i": 6439712327666121189240108004711515513379462031584792446129400446609440719472440049384297483035972842472082600694783067238133110198600582143589541058317516843936851310064206707174731971615401943686943763278388551011639976921427155854746077516909116011581605790433318056781525741446175632143657896880397028935820822552125204682151881996540575320782271954899885157490924329104974047676715783845749724106417485864572548380093731083005138487777139566605246984225092149251428740187788215037817450586032919294731522570525105515996937542886524801995233119080878693107170668636558109313565539463794090788646202097965568162335, + "Alpha": 1133943921642247826006085839854457324591086337148893131584778667719595815107560518824349657064129333282913010457587609357941089343050805506400138416944205869196971680687756678490713693656891003753754587246786950166124734750665524652910716568075088871526150389884361051671031986325065798283092972318782451927249559667911148873859554538314673972349502656110196949175715737915644352672304835060390591203539194284435969786708921390519874445812386663935450606927794475030882458716676541753745232356361494653422863637585768262732681967984278929104531315318212016115540900090687354736596291639550750922868042422099227298680, + "Beta": 2546355845821646154498440265375548796625753802194766361291306366929711703516137113030937110055955301624367538014275808978632440032565152358870758553837133827622875261355801244996361719525366603074351298525124517469688865374208852140609613031062012218533912513388750584453216347591334153809640136400795290584691398853608526159057855683617609477368373245361878906383207271096505847267564332498407901903884298961371714169775784102739545128128782417685303699240675621217358099548825295476742462889126253078050289800870728043417181317391379285329446713022600038813681800045417183487486583753288767555722094257133704521111, + "P": 75325992374511156988901460493633890861312724852536863840490059790519850160742135705450798151441947149346715847647616280074939189725175266154531725486663213798965397021993378833384202981373847204524798439164142531068778618875797798148047486257961413284209277722450700573497570860077421476493304710400764264251, + "Q": 84484708431912381191507284891311658594298096873211560902503873039529419725912089275989696228584226093034456553477516755804519755041912489274012153798395852780484271673357375121187150961656135619549522026885520858176120368514699118724790947261862749862464179053441972409220390761072616317037661873903915564683 + }, + { + "PaillierSK": { + "N": 22754629070822011612222078234427438670131467808775422391686470372466238191581206451852665393981521451875764084606438340653504569288580225664805298159930024693666750358739643437944394984526459908547595528760542768964821607665126990306727290554569902186140108619476298469347035086186888494985516971414934300650548163810044849659571636088334275463859876683306435561469652669542662668396311683940397055690832249865433617740313393003934616549702114319838322197313183959925164707394608797327376173247397032057166586936616253734114999060395769193766715266881872283032166594496830560248076420985154898994353923643569589086717, + "LambdaN": 11377314535411005806111039117213719335065733904387711195843235186233119095790603225926332696990760725937882042303219170326752284644290112832402649079965012346833375179369821718972197492263229954273797764380271384482410803832563495153363645277284951093070054309738149234673517543093444247492758485707467150325122749810942010073922069832514183466159038850972689725410136459155068542973551767311841979802315065045983185097617317805442571451777109765405834139364351288168364616669897547921297526144649970080306343465417673408348914676428965311731001666131568835203683234720700774947994486278028298917842426357382397173198, + "PhiN": 22754629070822011612222078234427438670131467808775422391686470372466238191581206451852665393981521451875764084606438340653504569288580225664805298159930024693666750358739643437944394984526459908547595528760542768964821607665126990306727290554569902186140108619476298469347035086186888494985516971414934300650245499621884020147844139665028366932318077701945379450820272918310137085947103534623683959604630130091966370195234635610885142903554219530811668278728702576336729233339795095842595052289299940160612686930835346816697829352857930623462003332263137670407366469441401549895988972556056597835684852714764794346396, + "P": 163447110710262656364072275522379086364019405419288319113380067235431912322680877479423110989933295898519152734334528150229459590214547594194930919058935620004920764971684902020574823909089468517720758250883980451317461822161998107927157747487670612144016013797813672466485807020916610070252129127925881567463, + "Q": 139217077450566855363424147783529445177779575941767791535999683997093670126527271837289985096268823874948094810744229242820014055933347194831722999525545763583514709083128799464206297049007623378833141754896926466099707885375840462377554187131064000480784111257615337885601641408181691088416941800878913172859 + }, + "NTildei": 24212016860952068738232580148891689710938323592713032850405089317731343407062889860062556553644041814175446139608628927086150634004666190165252432002440566310643980739173110959658938635246077085679172913531939428582390635518231387962847771838658090425285548587808009292218614367544020167667490090207522345272109053583812225552099614495400895998084199506865536057677184609103879032896568659540567712558935257015851259803002072945262011197715116274821239093183228854656326075295543379128468015577639295306246474222876859345146386944049307151586018026170221375026079899988239453498641070390284989917349139219479049679449, + "H1i": 18835078133089511643275514741897102560928951557285500132299210009068856219094024472374618722095847009275719680129048136196708456763848645464142142715010118589280792369140841347247526992290284170004086359126321955739308218299744612714719436273839667031176604793391576441207185534296291156162701077937009023234792316227173328757636108774090919368351127221387769631882138183413905969140333310820701968097184229597119806927188223719736611622465224115857973242447170574127363054438536760453689194702044284734764458848840453024390037780432121999118672575225267526668296974075429698520770298065792479313200649151018117468377, + "H2i": 19059418639885939279109023123884271431035352619382370427896333779593238652718262795568180733426382512711676933735936618603780627580965955898765878947203964462029159808059298688558386556679548352487079931785912229503224621665831953479255408425470171466756610857464742494360055177614082398174912079960065638346335706928958288942294704231997367797233232542314508872198412167022706779255687042433237745812872220899286057396155509155812584682728145964224008156726119866907215850155327391868129041815747163907321378809120548219730885878035131137377807526712985989541024310357717513076977295921457236049738131547852292685206, + "Alpha": 10852883841286464477234471641772611657408864168144866809424936259492924123398601995235825209313951594796493997233732273882988703035467050097303374145932895584465033436886174330910194378209635565449515850955898892782305965935181438422885873665680117906055708413747658005313519981065162127633952502466517395228078120768780417376493967739233262663252931914777746653674132815391000494340965671491959413616451573072632502183329232874128067102739786712670732351023901591535738288379480089810643162758931062059736118676818478634803277037550369053383692550792837725943295416583515055992174947169784667954094924153737358292143, + "Beta": 1848435642927991624575960399102195436516422633410682671294481087256066872395036790601022803280452863005250330182204483408987401975681199760261362777935601986265281169377280396470738752800317171723856294908215792624872967744372727300569201296638059322575270594573282733984926837303859316286456880987892365104038859425724681256740897154257819396177284945028137407939485918121889790716603034167131150465400827482275151065383996148689762149267231031789574962128076503594024112715762863034332192627664356187953472876461588648132108984382419818857879510602959946444665893463028073657926430057606832691751667361910590185445, + "P": 81042712641138931161558332225575640876887390821193417815048618388738608622660523347143105818385260006777509808992305027105160546060102989270960656868661965558352383836684036217922511152602313127744456311235062323236105131729628054297827856511885907457828501956199714990414946426919558465283948995090262276321, + "Q": 74689062322494237330744461229467209318530704853791196948947734088213516650955254866060698657886287869336005769075766703435129709763492495651679064334320159319368638579197300101673300113718504724312704810031928379105207270825082211622211651831738683824327972341081534959994382312211621930139210184282300655321 + }, + { + "PaillierSK": { + "N": 26643439123479632153282966082259408300548513630660220251562847673995772433179598167426625342798389502621365385580546994137620872339782337511817072851443761730932724619144269140453974594748883454079912671475711435649520918588334167807177767805129346066085772112285840572882293669271770702689253775937002206714480873854618206029074545983685724045624709493757650421870034079267871563376068883797230766888475672868957267869465753375695459637681640030451503622222194147801789092491654944074902728627305857273027236981933533680784320411316179441932211404464361641371722279358252210398277314994693835396282199286061054370049, + "LambdaN": 13321719561739816076641483041129704150274256815330110125781423836997886216589799083713312671399194751310682692790273497068810436169891168755908536425721880865466362309572134570226987297374441727039956335737855717824760459294167083903588883902564673033042886056142920286441146834635885351344626887968501103357076566230849632885793645588783563746072890158107628209540510788492843412991997889257868741854571055701396230756193681759063920571241468872342299570568112641821657001993345121406098797390841603906782391368311752171661322149629686065401227277438941417000710157201807839229364483577943181744325644604812236901418, + "PhiN": 26643439123479632153282966082259408300548513630660220251562847673995772433179598167426625342798389502621365385580546994137620872339782337511817072851443761730932724619144269140453974594748883454079912671475711435649520918588334167807177767805129346066085772112285840572882293669271770702689253775937002206714153132461699265771587291177567127492145780316215256419081021576985686825983995778515737483709142111402792461512387363518127841142482937744684599141136225283643314003986690242812197594781683207813564782736623504343322644299259372130802454554877882834001420314403615678458728967155886363488651289209624473802836, + "P": 149373592106111709371616386502488113496979543367170062025900835259544670136345132936754877614759186132843669421929437368342800176357456779857363074946226320559580063679589159434808864112832038101845141818972881655777275492505620619501580395162988739390044299004773933621745053747305723719532537970428147344587, + "Q": 178367800812828548115638419616108439981949634175223940763111667022640067255727972344738405564574375333321136935148952489224818318841245505909541406139742543598895024825375541827896269732790611357617312426337147681684400619551186691628176454423490067980257665949862598317803294091501748188098372106008433222627 + }, + "NTildei": 23152833656858422094593381148344995251592470462904634467397971487503490190912493266220003992613917740337402367406520108316868609599269726514358343319706460579661642347009898008497894860868346951239810961306709821819692553244984658614211688204515911796138987206353241559551498977440555223010477170546847438130116168739780201379609753272317349739123318484847724522592742742809816257766529802530668720702505225872742104933658102610270627614908882669184810316168311327915327315031350473604495064750358006675334079959765028084174343865101523898006043701411408119642339984642931750663930492012280435951802815718613985751989, + "H1i": 16414583601690613460939333348427386590334659601942333844752328476820536117795746645622317593885857451321489326948169034594496314081822944130119167166149821217313551640029360393664098343694651334428027745271808002416300625284815818402498710438332192636179345503377112522313423848906739883616112745677164049997965266958835173625565017930222231888067117934026862935859709901013586406034122243264460569024164145190679868128713027623479186511725284442518926715103736361763013399615742858633577003348896380185570323497254467447286781011548208851752855525687819335629574615166402484060843899492467321412519628692125378513800, + "H2i": 2196651795701633388960311361261032814335092960928631832190023260586051238568335788473378820942061184272897486425531616446398665757891927137127839961490623404748099140147407103466916387848827731279027032919526734325519037254620966538251077819740829794875824678898141094244446071344450106136999888855126035154731261521862482574326163332997979366856414205284278695261848425273147415487209241200010004249563759300327975258006548181322546964813850164757308559224616712330318265675365952167760433521462734212561103713038165245876968048006633433744978565839353849042653459755622051752933540742936978512285008653494669967456, + "Alpha": 16111933273734756480890535356135651819114122099158898428663793575169811762796992957036916869828456002167762080259603771642542070667068201794532505639051830849279730274610849629078170832122461965120337259059688943904982629085174213561563893391634282483545966251110829951086815870628489592450099909039090123606863865067619468822030995111276276256174573118067462347710432916392276331431057189563943036195137405320444825223904413079764681179990836298845407712496740479620295451423547888710143863181945058298847385674353006338270236724763804240764870194067238243971765628517199820842740212538366573198835203290848465150855, + "Beta": 66839866677519901108559579832824576970009396743940246066320286980422361932151080599264682037183104367308935234222673103857786902541659200539236624213934650240997807977614596416080898284111833515739458303152357633427024568436637576389690487316745802071454841878124182414740659929713566786479438634579292619834869779941893599092155541059639337636208010023589496209733508241250032676773562696683566834941207434334486406318236470419900108803642138092645739716075515524578702433359175652547964873252072472637547359357615556958505644456373318948184282337903294645531444665075790145724279053289577845464103242444769747951, + "P": 80363931290177441667649437082347847606766334734043036046019756101033424635972143112336159247531640937018625770613890424640540603155141821207077214154627243275214336717721436007361202699821496151584402102581024249999741852734730648231244077649211516199413903497924911059904064329466711036888291179499255620383, + "Q": 72024953499531883039951954425884773416678632915818834731825468204899689822176694736483620045905199441040553190142503997693119482431190904186046147767966138410301582664619576983722727699977763346752925570538602035026832498498328170423463307680849451752320657244550736035412814845700298393060726678628070860933 + }, + { + "PaillierSK": { + "N": 22282240729664262892171813956805271162601690274871364084556568321704551843326927020335960533823871871169716385088273021035920519673791963714479777124413522062816491922486181253059557356681886267936296173985744057291621036046793267123297599326388536831632114980848917502692064564884339901142924994750753653705238561204194604340345214565110021491214593384774840841812477482694464518124247863972994093851256991062420832454223654091031512641214433789089245470566446547915305437672100528785359804870724392212034510668544247023145036294707101034429550175617082248695037629869800886939165840986969034323684055889717429282769, + "LambdaN": 11141120364832131446085906978402635581300845137435682042278284160852275921663463510167980266911935935584858192544136510517960259836895981857239888562206761031408245961243090626529778678340943133968148086992872028645810518023396633561648799663194268415816057490424458751346032282442169950571462497375376826852469750201022469023443058268747827165000450421464772040487250131383303466471499089283798122074371335665048818977506932697547795990984710528788889109577968868077769116521505772336649160625133806571721922200601151661914986754840329880590681800550679420811986287788299213181522763617385925008261145595810454303898, + "PhiN": 22282240729664262892171813956805271162601690274871364084556568321704551843326927020335960533823871871169716385088273021035920519673791963714479777124413522062816491922486181253059557356681886267936296173985744057291621036046793267123297599326388536831632114980848917502692064564884339901142924994750753653704939500402044938046886116537495654330000900842929544080974500262766606932942998178567596244148742671330097637955013865395095591981969421057577778219155937736155538233043011544673298321250267613143443844401202303323829973509680659761181363601101358841623972575576598426363045527234771850016522291191620908607796, + "P": 158311068244029288772258102876940233275412332466144944825312348995476990956999268099406394278497384142118921875152133139287093832348591595126723918127915097090191803646662364724106076289988364418287635440832697625066820127782732442054422506502436019489479159854369679390709299573764574042696781083760038593667, + "Q": 140749733905637004686839924737426927938280209379151816012664870932380594224250417305991455424016935590204272624057655556648826826896421136384743333282593714669575400982426619387955407330468414650303030826509246074248242657243708831193764068013287387581585894438832781185411014178432610264464983614336482081307 + }, + "NTildei": 22686046079360374772425847141811858477694860187748404768655134683871478564221840951138421057336329934236440175527384668097337381930560598071408699025274380904121194214281970688330819588951066109639700076933481173511566389051861587982791783345496754142910011590892755790188540852000332858054054875900465497405284843210410034066115815882766069314732006638761270712083819205854336024891572999814186077848770590539845381452899993800258854770121203138574038920176926502303427751846712047964548663487191681671329337344832611164890300434619051336527616695831953800191907569108131749478188046575209446970674998593402311733133, + "H1i": 3032445746977801997091590631794153218915479421527547573407350473835481725683321761828303894072911358394480703054833313230213454623576858512814463200748122734093742258603085765024331882374265075032105153190876797152717027547798969824072034304454486490975709888198015514183697906766463941330896692451736856089901448988417945671415104110224322776060860470662806660862276974527355181407924396447831696297120941927208421663697923063366128198016477664262955351499774132943725953025458686238813807920178465740519711375432307320236739858584247405425619359686800794007766011286982727363623688690883967985618377873810636847670, + "H2i": 2755978893576726203740703932262797966214200089223549312387143843411846236454648811394837242136985649302079153738340766270711613106445136281850975135125954029484765558230774721191328757803756789820873111123075215870542424078927570901634386023470029125006798419653122659471895367906131715147518666300627069993361333347711478928507164367578604883317428762893344561853543028963960483488700310660130915135129262422500322975803493672316411786993721922199590483099985433546230805312143193121175571703820148017091653533201540687990668862781722729837684802734401960993012754494810133621398323288080161523636689922231661625768, + "Alpha": 11679176680031893436868688379791459087233873213622899653090714519523041122448577482385168747413919750317502713446788913511906646905541916430749540911430753953207991108189636288162066726568329654183147495972215340379030815559080411390023396089388713752381669954564699053700697462996144818525839482004090744289146449023538764941835003013254961070430372825575383036186402036443850774512469951000440710486227412071358701972457694256931952017749873532602601156109222534668508922407020535537073702836246713319252042584025221598626832619875325198419394708804378297062139238749221663245052529802573672861348125442535435415560, + "Beta": 1179139300656709625961956092400679062060717467687071262209876838493292858637436070524437891111711643564117229734647346780472426266459784873521872945841940119229937747454054628734491927635793198983841217505629473384150363108202368135757445257738007699241099873109101068988553321290253602154361656453124433555235474510790782459123068546811803485565434721101114461487260182485615961282111133351002770968343151648954397260331178933850856733398211920194142017417075510850726233678476261988839462458468185547843776166310690979315686480117508081966634283733188086742655656298270429261588321926959804774422622836126540448267, + "P": 73694564668654671939995701324622812805725107304993639502972290161602285639457422068197024599494062883730834838060982537608808574873641689596318510627168753099986467077998441970613555580248025564063392302672319302944974639999147430208719531844028132970179375617657401743943460890324228064260276403179381903553, + "Q": 76959699067907252429828405720708288211357056569804155267152875475521659990093917017555210916345394396055842042665950696448931705842296810390643187526502042995914043714288539734691789273176186648369730969683765467147610481241669616898866711892018820025881642980442522310206345092232364528828056376446844819159 + }, + { + "PaillierSK": { + "N": 26169182626779587026893614466978534499661901354584226787309951684045005690788422245946867975333666384843915316246662904666672525824149602792078350261721553941716125742011678363144675255821634370666301192510684033682124022497661196073081627692182978927167549372888570954189250186048318779598273257828615684202846391519457386842288544815466793455917618399498907235808595150043602560923971892244855181526319611113158986476156264512040513271224941826577952764166285137595597828617748727745684006027593535083851052839526344845520406454415274433636427200969430286054362121915366096049985231293570275374118005654845516094173, + "LambdaN": 13084591313389793513446807233489267249830950677292113393654975842022502845394211122973433987666833192421957658123331452333336262912074801396039175130860776970858062871005839181572337627910817185333150596255342016841062011248830598036540813846091489463583774686444285477094625093024159389799136628914307842101260903971109745623471447110154002054315392425882457000511839690183055683702795694311038471176877067245874550584769420594927644378898610798623109701065592517972245495992957043236688568410845159161746809392156651363726029522368710668380251419723189065301899907485312142766234710237000779883953643252483097405374, + "PhiN": 26169182626779587026893614466978534499661901354584226787309951684045005690788422245946867975333666384843915316246662904666672525824149602792078350261721553941716125742011678363144675255821634370666301192510684033682124022497661196073081627692182978927167549372888570954189250186048318779598273257828615684202521807942219491246942894220308004108630784851764914001023679380366111367405591388622076942353754134491749101169538841189855288757797221597246219402131185035944490991985914086473377136821690318323493618784313302727452059044737421336760502839446378130603799814970624285532469420474001559767907286504966194810748, + "P": 149274798707388102445618878109855307595585472007317690968743435589389472479599360997970504892312440800808211860965546423471656851821847870730131313530824938527897949830922828627295513787225646364619391482704162009404861985574252109741073755426536817014135355063963261233473109821527553215730818160195137051727, + "Q": 175308778530507492900031717048934039691248075726675543816172334088101721038781142624807734280253035820601673445651876898713567661605872358601602048504275163123208886800911812645011355418677570395738042572508880108663485424103600987134850606096515338436426951880778549284042700998041162390479900989684184231699 + }, + "NTildei": 26949259604320329304536450610818629037843714090474106161232272624441334477725122710279747308282083845237671497115433770058556065216035113947835751858531832855773841494858860915572039513775607871041753790968812818315065006758970906998578389263871239446482752409922085092205074258132236742010618239338080884875833056029005457650575703946180217603996222190365268873638852829016121609412570514466863782511661107800239268182942675878992303640682226185165050551525422094110299777867064329605469068452769542273703687185430854999261934761571651417788069644969259208169608517734791308387713353771110530052267277549019203223941, + "H1i": 12536756446887651491596090711390229470272463249558916862122243258210332546673471236660488920452499947251622360380706194040090438672837940180826597977749177721750097748375761146415833912466924021573745697810554749112831759380543816541007043303490708306251517590037149837013427282403907899595638075905241659955638729952829874840443797738628606820940756245577823163646672925501838954619362138661288287269120299035291256653367442129811040440112470714830956211485951583568877864477602110585225613534678066895184662321175121391670430785071589746201009987140064755442279565021243859091048618653056608103804464465067377270248, + "H2i": 25750301506289877204962684749336755240803024497001762345788575803137291810029494841768181991818291106096192838013545827248578041199471627895689264489042195890641099075408548947039446129273044784081361661342699783714644108493664349418843840285796004851541111149049457743971256343400801367367102162454829614987982546852365687260325400986723037998421928508585304429392557096969423070791611826454356704345406955157097568747857666592403076111662799967040769613818112585834378901758207281306378293098969709540002077955360748966065308437450028412448681326034275669688968187059204236789155871371836728254081079559038986944556, + "Alpha": 18586085099048762751007252806006682904373253921001849829524864308927872723872606437285482010168853097803960721641630804709008873754310992983574778303733159271970163873400715010870696106362068391293313850406313974089602972582856141404362348881400966674998266913176271437153365851487930917918120568550412166786018763041394161341235702906804381550211867649633402175736834257969134228848403629665942440352017626718432094022599655342992409681205914895921516146894467218558206704850364477245215255996207408046463599536481408787552211448580162299600252660422707809666853323070779081270049011256780509384233795292023114922519, + "Beta": 5209369581528126241867316791232480388668366018773612406247211684156638306664057189395970193442504798320082037928350054669302544279707424380296011601071523210150508313799112541034289391521129492965318462802142888302700692779258613317123249355601101497512875664982259311427678917550923522021697848591782330208377826383914949589472413626526849124073083905914961690511264924400260670599146159324948517868090713700311200353791438286686195024975057338066729922712316790458870660936899044854558536855462642506271051463878899557742385020105766326028832595713664599693632390141440537784612176498994006696121737861280247876470, + "P": 80647143368533455317011653231969864907040916381425009439603652705778988682950230302448057733899115454508888988906120334487816385724108388609954537920588383346769887613838713517522725112369922314542340079404071026273644543836816363482287685660019772026498831590441583454636074732219030286549734087404510080233, + "Q": 83540651530489522216160975911164255180726523188155812390115386766394074000134049711997242455530586591261262342010536349535988363041658986736811612673840951866293778609204788158045257473823425428466028750029096943853827876882220496212540018696084664411180555634703488070477285031485893810900618101900293579811 + }, + { + "PaillierSK": { + "N": 25009876275391172469509633242191149153493363553073692173661319616574250019908199579192248141615661023023669726901339045848147417702986634248722301796650347340816823991672876397823102972872593468516037813027297186868589012179244341412683576956036419258289333117937489350089612686417029768622388337540239988718900204049610575535181877373393229039621625594371675219883898826491672804156748627577017652021648065388433355503024011232954920861424846467580181708033582517624828977614367442104333535486954656617817290546173491688333739730396664258480173829257959533195414207785969374824707115147551866592769468322913412727241, + "LambdaN": 12504938137695586234754816621095574576746681776536846086830659808287125009954099789596124070807830511511834863450669522924073708851493317124361150898325173670408411995836438198911551486436296734258018906513648593434294506089622170706341788478018209629144666558968744675044806343208514884311194168770119994359291808246631226896792071063772813214250032305495527141590726384633434319887299901213792771229340795501225377425165379105684755492821680713051057994940772708878071208146517994147700840982012174962363403677619218685166913187148733028006579914673707125488561383450459124936473796045934716751765922771220588831242, + "PhiN": 25009876275391172469509633242191149153493363553073692173661319616574250019908199579192248141615661023023669726901339045848147417702986634248722301796650347340816823991672876397823102972872593468516037813027297186868589012179244341412683576956036419258289333117937489350089612686417029768622388337540239988718583616493262453793584142127545626428500064610991054283181452769266868639774599802427585542458681591002450754850330758211369510985643361426102115989881545417756142416293035988295401681964024349924726807355238437370333826374297466056013159829347414250977122766900918249872947592091869433503531845542441177662484, + "P": 165152636185976356007253845695398056578396088852663336882279939271324829604567049611760574278029561749525554205088881921812622825533970207251302313543844403483385820919348327485587033715418289626995760922703624517726811937671033011211110525295279379772985125450802319551528211776921916946333819654009035033199, + "Q": 151434920162145385590481400152204554543164894527957599820166117953479334777581775537671535284936912636457046447604371099772787050247514834226763404608192696385300740401983126323344819807512017066094722268231429800273101418428165191255903474615265902445306315434248805400231311278760516142903803126463200031559 + }, + "NTildei": 30699304725561606321175739770944216678368797092985078369544750203662834101305740919699109945687198130415221406890523543216681365253775930586732141245365204185913629119546173367629241124594792745356299555085451566594538489937313644659714739547675633242849077027504343956645658326477386334969188328502532819029365196934759402987412369008664595487225978658084102886766514689651088501755084936373227181833216570710861163794686548609016276658570328501813646069912406503961742557593067978922588675800384376939789936661908180357975015432891727231132543748378728823333225801855012709120448937193974986382652791444195859268717, + "H1i": 26732892263886054643076035208516824181371206471173376856950590978351417018730245245886416021941453081434596344355030570002393360961088197913900901297431779132498907140526221095653068263692844212940160582416129574257683157028004951521208316070981908330488477078370243937323405430981489481077301006380234961882096698729363649107680625071578606013746174893575469790061642376713003276796567414868367814899430467338552161415935247223369763332973988977421613066832049049393394209108145646132975662611088692710211335285907682963534373631347277840968331191897368430458793235492714866126192526856713181296878584929814982333180, + "H2i": 11746013878697435333912512532152332469062107786724669220602400938300850242678920855446647513475655856897489209655860517406402429209469208317919117617717473845130502947427956318596433436338762689865214756408593721724917036197970550337642592092060609222244900939134553462924036583549727750716529771372994146545803388408597937289887886365857411876270808031828731963749883864179772977293481061485791212479868888375716667173214814019228594798339244838017070177165348210478049438813646051234571455931581719358474229811563290883681476936393535834215979246342472189094124553002752174118444001644523767848595281954915920779483, + "Alpha": 14251960068243830377671500898379080968932972058859774312358008250869790919910949992077400157751975171772109020532628217261151092849722783350445887943585110005818053754976339718988085961103800100838164091269468247413757706314218512600078807551684380729741902985359536146956912835989414601184182422913066272147899622465062298598032499906335575019390862218428084180069297827140426942582369855575970462198399599119478588454706955765296779582497557592057029360349852866719989855420813875657322393276363863981249850416306357655585703090986573083965963434656765474630178447483109376891458267048798599095338987106948288913327, + "Beta": 6683578767052642633157368682193524788392788407162385346359264300221069257539287767355636154425800676394494796329208228399952394840208374890872348165638825707521405864317740308640008985051065637797815227588725767387081970018692527623664585538141325913670245440233324760937458762050155688843562131639324508325033821077841107527259593533630894430413304308434411222140127048992327027646153580717306977953115555700482629981952362643971173311136408486644567903139401772141063981880464530069290777834213988731875471206998830920121539071942505204041497013939496553416671752597838105144628522781654555342167449611651675610309, + "P": 87463294518541318048993611115764928727997827794804272644216469957492754687930126181751213488236842372390929110515042738809212864985149434110020149831491558806608620920200378937497717788071361853534253957232620124908888520507890670759841402895752370228809753140453122855985892920378613589503501722238001761449, + "Q": 87749109196468896311313026602175193552404816761423289691656838026193845874646109463556261815959884406646355075624202573777922703833196927669333245889036916568572554939517553066584608266262306051304210675966541117267197177377866745392711728439636505593515179501321920488315440929733569543605311023600791320991 + }, + { + "PaillierSK": { + "N": 20866547341033953694275392572293632865809840383215469618160361728895085664031802824962690535007598636319066451712343185305098692574742364528843693393360987380911206480849159440707147150935222458453705136663032198932341373076186038279669580024105494411037682864707592726445613372637589726378393532481968325932055686320718001168160301477721839360301446639333339231396139572926362644196148267417252678839054613511971088220511038694273731058974672791243166521475712303663003734971699775320281063342513345248240923410504952991301709793894029006253653676981461286984577342295253781422991665516386139211795436587244325873521, + "LambdaN": 10433273670516976847137696286146816432904920191607734809080180864447542832015901412481345267503799318159533225856171592652549346287371182264421846696680493690455603240424579720353573575467611229226852568331516099466170686538093019139834790012052747205518841432353796363222806686318794863189196766240984162965883144278997760853455650395877389600881461330980694571485498462693119391961806962880752858849334227152821513240578292972251730236272677709514848730742059379205171898284765840039278884916942352331558475347457429441324265454844567906561467261014770666639556940092271160582112063823806723436565284638098639930066, + "PhiN": 20866547341033953694275392572293632865809840383215469618160361728895085664031802824962690535007598636319066451712343185305098692574742364528843693393360987380911206480849159440707147150935222458453705136663032198932341373076186038279669580024105494411037682864707592726445613372637589726378393532481968325931766288557995521706911300791754779201762922661961389142970996925386238783923613925761505717698668454305643026481156585944503460472545355419029697461484118758410343796569531680078557769833884704663116950694914858882648530909689135813122934522029541333279113880184542321164224127647613446873130569276197279860132, + "P": 136259750709319651218671655397726531661286181512966991295962770674574445086287369607118311813102250122657420608977123734104965807447429127559465760629322794202511903780089120973205509054913737695697554579381209469357546256564910745613720718149292581374571981978534665208304170764078201376210910866720980103447, + "Q": 153138012013159810030329030569333626877237795858983097129179876865549415186246972048628649327283909083670641130377329015665304778981888244654003299362270751050148034622078974268517784453714902889426418136208884639295632627639982447516998436802627372330891480132176795050463367104694490962453956444326065909943 + }, + "NTildei": 24437263448543629147469512102360541416575702271078863490894389494905431190747258113024617795133138535044984402502686357130124162654559662728964260879346099935022622216191309811437984035309680721406649347196075096737782323565547749509644253624239278303153789946870626140992877771019592481075651162754632021710365888624181097199434733334479619428386902269781283712261220790537086076471239599010611616194338447719136240232047880623327662539670984942814217362528919278385510173170476379523783845206208177279923717592898477880804657220495493932655314190185930612601581317421220527926665283026448868954828546508117535955977, + "H1i": 19978149370065487698930160679970775565093844802080906035455695755054858126686734582869848189174704124073125395637641509145756771890801744490500957165784994369263162575253901060763784904508432649109978101926869169100263130940953314263257451308832311272888136679633469932608364493010807458602114030588699127355032348735877196215695645552918141245336927444649997119751016257993235887537871901989459694519824715865722179834765916302519019247962420804463437280867110739750309773753196554934499111409517061278148431159201354908199043075564284931718852196557460538735294799355538332937673780087811856870859719562961550309496, + "H2i": 14611701654718215290135524138262146538503226311079883275240983106787737300244154260263265623990839184674841739919838720516851609368525488879921784011982498251503757573295439372954453767249168529172731534629479884236698647327209524785300136602978448944123205627058964989353810312578130415002514570466668538289974104449242262425606306463159308650490173017209479520302327619497548865534492685440231750827307288296735478688092262831923551522307350379705923765307899844471512352964607542912692688426723477212287578384436683280649965009096434843796912819649081162859620649168576652290928222319317709142091352275469427322388, + "Alpha": 19857985536436906932295572940767146808214777671187264859474481718067924982642749200128684566457993305480034464088437719989616190361740004265709193913846503582856403906495784097166343968623643030847214162338019241601052109788722646761451136808020939669750942608525037832231807306010304726166100475913821646923588903747224051316956458119090135679800064386497389322377827170813741316785926492157934516273489413027515356363646005972826911847484190168210476013082895014389743534292858499232112998790550471901338036076170672170855168021008483441253577426101226386181871030539992227170266493760740762180265118469153128616801, + "Beta": 3259281609081298866231283885862288331380636676132726556522500219327054336976503723880135460378715384573755453520193689631085691340770753847794365311836710850509529027109306535553144954233049354705124012260944611798658990183437805238024265483681678596495071853733574608508150950168778084702918242633546438255605834023967554220304918313515294693132496324662408484290646405652369090656027704946856052417474821548735306949925683633184408304354391799347496455904122833636496151336185684910767006154926165969529931705337293659125381835119207575321482791459280768288205314553790674983649407372985844408682977781383856345429, + "P": 73405196730714583805312306002060954391135746987712705664529758144263790395659354666405739957101798971753551007292589007555966329111951152085709667330414853472625940762132232086111504472869554152036855902213293122024094449898474171964215132307775309842964812314813361480236164159203485566962135366900658445649, + "Q": 83227293628103793390388792145655914803776934165182250253331293011636247967614250251702288608867716937544784481589401933390181327567941847059480132056496965326428905754122752896614180146244768837835588500629735756970834521050069610584435102900845242326265082737527362740067974253153126393105063815474810806961 + }, + { + "PaillierSK": { + "N": 29058536116035590840035097215793433100858437830569017475096429341465325789005312302596210413792167572731356067639741836008936111863270565180775762776678957353167676362055991196009276515568298904229879822853353187210939635779345667883638612031975320525201764810185009478249799183107731750920797940058261814026316142595302301561964541411479308578431238153388584127699241815728976800246176524224820052679677758361877967909453463521930580427532497620440990957614508808853191528050898331380222249167851266580591097910000008528156818790223075689224169067382463635703494829650316482748935978649120939679031474856901017999241, + "LambdaN": 14529268058017795420017548607896716550429218915284508737548214670732662894502656151298105206896083786365678033819870918004468055931635282590387881388339478676583838181027995598004638257784149452114939911426676593605469817889672833941819306015987660262600882405092504739124899591553865875460398970029130907012987400832322529588888357391708421044134354173841836240618846285056136242075302693557108271822148144330763189460122326848099569158683988718549968475689577412366575958280926005951587427899957729790497842274425732438290089380612918799983403239228061528288864084496248312435915427836914702934941866980851350664842, + "PhiN": 29058536116035590840035097215793433100858437830569017475096429341465325789005312302596210413792167572731356067639741836008936111863270565180775762776678957353167676362055991196009276515568298904229879822853353187210939635779345667883638612031975320525201764810185009478249799183107731750920797940058261814025974801664645059177776714783416842088268708347683672481237692570112272484150605387114216543644296288661526378920244653696199138317367977437099936951379154824733151916561852011903174855799915459580995684548851464876580178761225837599966806478456123056577728168992496624871830855673829405869883733961702701329684, + "P": 179029389867848567784591081527330929517001843272575171739436104412494975355527450398870267222130406263559301697311849935295192606277275334049670000649903290951044671915191954304697813913666169050597007161760224285056581236925416498854135338538805345777420851925341564124816629670740416311159479931770603241919, + "Q": 162311540789393816403235546535135560645527962432336474722113141204209340740043686711733241813251063436792287291896959890436249503887244849291384005585450693168994939573854365172349579454269637948998406199388319366520058792071821590403227250387535233348345808732478293752288493304551117497988260963427713427639 + }, + "NTildei": 26183625741068080070506887731880989838013763870795553420570344092842078780599086628894692740401300660757182338413073265120775585536033921227362405450203210436817685040619328701975323317166763691449055210198630574031767766538456076787136349178431897746541043722716640927075641875947690017056006033061756754250061567922112775498644622318552339246543646679940766978448827382509359183671539174840687705634599807491481224056602336054969597842970091859588386068161594329280714638939669969937434464259955212408749017205094173338711608642704809981964491523652483956816217178634113802630195620966088677516365096737470061315697, + "H1i": 12597477114990805371912525507948479829998830436820015065000986686667943541375775514099005841258729320435799420273048313276478865380344558638030041744496628799016977479414079891069842614238419902819697275077416886421138568052512057687935778272856002198644771762737155853572047658577704885910659161844502972049200150108419353959762802860320414823076133795278370634293169129208035579941763741751070817767566582461277049821372819238588108366385833127834471584288225382823119522440929317258677779466882155965740174478829552638637000436652877037267078988289924608412763898472499478689427011592150862335882594937991679495631, + "H2i": 20999066908927529982645695227450413384811039639097527644412219116539835024853717087686813762691414067396255647737605945258122494955633184586754988921974736723551434216002627618570738208601818983405979238412527094674180708078886386817171027609079881469370894050556368379062214936148818077433548153636144929398181369958932650024951811309038205934926140640598799452697772162589746631476379599214699246810519121817038089635413629616771306434403475379832129053745137779697320627284530996075153057944101421002039969533003972647916182894067064434594499847804906903893891869277809992624114724679987712676645186602362540737449, + "Alpha": 18529637416204529962070718182282093415772625929752532283853842175684104996705145140892057246620825621805263956705057403006948592936048383497303617858884840290143085317462577540354491320165762630169780714843892251745868163516513853015437863419415923076665995105724460962576699229184510109301349742135237529088903807992369992532442938659329055027698534844719724649196626439619873855133148435949863567887504727541062466719858385422733920582563916743587936706050472616049484711432090052126871872353494883728204421911854704031864101848719029116419086680377391117563464876393887078431763779958961366092321460659893052658448, + "Beta": 1251290389200824284992665576977095268847087515794826936478063491280098544167112271040519562526229071240465563472686990577956341177230727636486953983031557110524104356484860982651532956956576053540693000532072443014347246827022369202736176002291607361306762607763509065811319766145645904452596131406599994962782253735164865953869943640929796475419830123307159193527859924957651816819904879452230795151400812549816384369464459121998882437512571405248250053558642572938292694972209246819902389044083405215906386966363814798964625586827422754568022016143904535533526435604424438929789196985205547167745213150840154373463, + "P": 82035462574735815660441201384947208305524298748158123099426230634569365159977003172928831131245554350778710450956878128698345781676209250894016864612791019801368864458893290999204844100247758865286533950931326735149304144421127755601273008919848622574299771223054804189796052966758966785681076387162591493201, + "Q": 79793618879196040690227421729768399917783456968430805877348178194280303188809926242063864422850876331191069884574591530895346094365724639292617023244006165582137508365656420311245376352929632217645030345647592783643890467415515039945798562479898135157753323525640069524167742441259484654901114033655322970349 + }, + { + "PaillierSK": { + "N": 26195536341062750337246373738519774770193400707926670530036752037530531694878557383341202659769976763521333645778230959226974577857256542207803178903311392758284944476507131797627750745521972469484110714748053611544936503228336843089671915690489471334958717422944244488186756742797524366759157910764102155784207767773627028487258543564269240566850907061831389148392772722776841726293903506788595147838335330244600785585567224710638382369561833372695441582166372657060099961227993621821669630587833826510651195870502901550265727679635380176139454193842453256683376596823164239351681274339524999635947084674974631363437, + "LambdaN": 13097768170531375168623186869259887385096700353963335265018376018765265847439278691670601329884988381760666822889115479613487288928628271103901589451655696379142472238253565898813875372760986234742055357374026805772468251614168421544835957845244735667479358711472122244093378371398762183379578955382051077891941753608701738995041032457361331535654192021522270070165086179652900068545323500996056947224781495694066378044818668044718513119274410068401587415017665945438719431478245519528418683653849800148034184188476976678162939733371837348011144201354858137830444310805950196858610781566204215003070219870168292562158, + "PhiN": 26195536341062750337246373738519774770193400707926670530036752037530531694878557383341202659769976763521333645778230959226974577857256542207803178903311392758284944476507131797627750745521972469484110714748053611544936503228336843089671915690489471334958717422944244488186756742797524366759157910764102155783883507217403477990082064914722663071308384043044540140330172359305800137090647001992113894449562991388132756089637336089437026238548820136803174830035331890877438862956491039056837367307699600296068368376953953356325879466743674696022288402709716275660888621611900393717221563132408430006140439740336585124316, + "P": 171653446677900597264757504248061306221239319721606913170686858391811552113101626100395958205289472038024202819857100667801186285658678328963695975974295015995902330981421689807282744935312311339204943763807555377992056786432402776629559505878348835883258823329770611985767958304204771977306432870173968064339, + "Q": 152607109545649899911721145298516189321283699065242094891913505079230037090154878696085295183482866818443826676072787953400169845354334906928570776156745750186758767290080892957549518344821914875377883729741392815947791426459302703487606285254388145139229151881493233648691752902911797652500212064464078174783 + }, + "NTildei": 28510211440672556581099691307481564995286559210311210606945886833332657399185772472063164395719059163201290065084870413941639812358605690753059381167945934982772665741513043192008304119191099558597525120657963828054166885952045058656760079341892315168846565702191710766553948040326675206092628379088526809762065111127085728144527673314078313051053630755513922310667308091239346068966904937585217909847385614922844522534473289510551755637895552909758106044169083639849332947292502595759949914522393020668004890553722476421205949196350026825795174204187896600622225022167501809919697890188412059136888031254205129678713, + "H1i": 24068253491801016666536859767972359749052796434069916187097233410099204994045071820574234159847596674156464159258865755219593547081814964499900479078634981874682179555428358715655128053685545560184641403868251753212348689073278109931395236789795539555767246904957125384857775641964547094207472257112431819133443464906311385606760830621891948469101826954386550827210676621953077733852610026854158397782588793754742794721685535158362925558643047388820627724694574784143945814345258007651218425442503326035417747063939204755134036709722200717095771398413161145584184375671802522849297173095801022245787469652296913390997, + "H2i": 3585035209678874314922828004421379749496465876798853115700188460233811634515333079956587826714293735144504890482872147720318944979218935531633759630590704178058430786897921087694046325328700701410094327681516777861197922764434525284941391728865593455517144713810924205781591240866688260730418439812532962863200336928033745397508524882297242691349523983018431575602304789383709616131007820954896275780353929803389901110804769326794711562291658336194233389473459486126407574398166387862879567542322377168943699619578798941273760750399355067140123159034334218305000523508863074230190408545755400293028663357753074404048, + "Alpha": 22414128402314642122535536352187549917906644474967304915458861529204662418060391824765729568447799445792674774222376576126533684771475299945277174715451225458379766604398030236584736984282721052574479517286231070078829295737535668587537534563077209988221713238064036388273468090790860797321866887984748501766338235130228895428143876409397151778734073346278746328937277606509462381180346208278969217055195933992951261225631954163213587796628164987917576287066131932783914623098814682168086876377101931469198869321019075904934827609052557520350734097254766369082956879999422974802550883392830266383998921136987027156719, + "Beta": 2286446406157824816120318076891668328795267880344110059881230772417623088726937483756356512151832671410634962883168016622618886458151165130440870233494600130931759901722279162821680774873928296824201646742391770404723175432851235489016008141334507568430814170551568735680480167613724454105049619068228040085199879578750150520404460324903060586561406407738992330426219358786991308567163275958364499055080552613062923374392671142529976311126720927802618931086723128828222225997756948837777022989379580099240136995761086775608667784901573412791024810181494147491630443826606802291036949234116170353139531693955228326009, + "P": 85753283656550033188371334959807344720288974234136527414296550305477853566687049459961816897296064891830133559693878918172501060359432350433670120874180306176470119834242710095276681086405348196563402871314003020621312248190404681338135102671291202362956000190485751325355398873382721710196275183604933278103, + "Q": 83116967143959859920363713500765368791675662393722822447357334844622206398494215861350920345321574220560491310631285868733494866451888580662244105159883545809187415939878747433186607835935906534211538745737849916803933146202694514626248491430378367105501238718430622759436493497595178437613071024663034668779 + }, + { + "PaillierSK": { + "N": 23829884647402859140729597185051245932689158253811007387849844174004622010895356716824754598632349220106493699741435175799932175213233811749025883647317370284190055835743173357231183716599663999328514153163618536053404851021649597087977087077016737598211273790900469469790876351458122988089355331012866430452992783985757854946578629545676268664737176408199375634195237015452788745227305868242671652743132815521243189726235441588374059441107689503768401200954675385295981046645761348104418267529371410280565994549859995061562691715755535237156065472064759597957239978902667007772753993947421919409367181399668355865801, + "LambdaN": 11914942323701429570364798592525622966344579126905503693924922087002311005447678358412377299316174610053246849870717587899966087606616905874512941823658685142095027917871586678615591858299831999664257076581809268026702425510824798543988543538508368799105636895450234734895438175729061494044677665506433215226341070024266139657802009228454472848191507924644223246991992074187834251090685251223796860724396927312202843615005728812742478806829751188579898021592865313351850634741108693473211421029721376689344992753829136220070157071150466681919952990440340243750259865751235325370356233327141050864064868513111758778946, + "PhiN": 23829884647402859140729597185051245932689158253811007387849844174004622010895356716824754598632349220106493699741435175799932175213233811749025883647317370284190055835743173357231183716599663999328514153163618536053404851021649597087977087077016737598211273790900469469790876351458122988089355331012866430452682140048532279315604018456908945696383015849288446493983984148375668502181370502447593721448793854624405687230011457625484957613659502377159796043185730626703701269482217386946422842059442753378689985507658272440140314142300933363839905980880680487500519731502470650740712466654282101728129737026223517557892, + "P": 138145552038048363430711659597036156145576623838478179705790821242737351822855040309752426499566734866523851884545653575030687720153503112888255608560272081760749095131585167484459688987586875425000454034549374160778961383928332013025759397066794610142755932030022268758703023343766182134588249185813341810787, + "Q": 172498385187527267543899429170286812208583935072450960505462045834382891223080325485325504794772226030313650611678330387858414107294684013720349549208672676831530682031958793673535736482341781476875555007652348460643416189526269860290400094117284500313964315370174088273338503949373635546649195187631496497123 + }, + "NTildei": 27541533673704838139999311692847458506673282681628778994791585699199762181765561665991338138685295867075281320538997529790819839971823132278172989385448250335838936827748250068574517759099395965307778003533033017595135272467841391532926363790931456307765447985982247823714910965275050344120901219425790391431664916069399733063281486261762959210384671479588904984919299673684285653969434902755671321234420999035841857982292966473534071407349155813547840025564354328239096635697767399231097211444575768171899835809370271051072719408066836578284428533412479712098056597439901058409445165075293733185921967233908285369213, + "H1i": 7231349892436693547117938131928997957972738879353676129620369580038354601195403173173393035968224086506027575864433486611555330892969496918025237496366542908427786571694996339808048142356246694585730144734111064740747779870773439548000970054112147236802241526715180427617847101566522944864128879297331485663319080072039235130587950391697925779585996170872368928736790077326730863641137704177319465181219725375452484679794985462225563754752207545774844266282992305913641629821531334895712224133514249145650992309393522034973215297552980363978782151500507787952151880560730987146140512199645162498314383425421709943719, + "H2i": 6487534044907471523394742436170100508831634975835919011991679715797252370271671806619459236407337991364599568817910332380876658143944672072010066891341002817325403687732242758204901101263735092040136427031236902772335051884935897091094982262470268799518251328895253203203723802447545704395282324008257347558371618264295346239340931826031886196860993246286685460840051514324008224747452240508618057600195803569486546909459040696367675226088417362747188750095856438943112942587699287811620866667632191782898908032944736669426681220567873890801914118809912404307170456790172940969140697025483385119888012922410891547033, + "Alpha": 8762634014972522479236447989894139195207707834835173613597703233037993657197028726595046772460857492729877926366579976498082255630558431332623532291766885713059421157908649485174595463224289095440221003973158234871326518182071469618449557515664550019098833996772649286183239578438498053178904337157467146647078672103992631917877586258284347291947069615619523160312040649086038720695359113752934326997413416550925328875695008343338060132070707908165061901521844158606674860988264734058995760607995094687322881869735696757803841236319524945481168411794089206239983555600890103413164617989610349833755314156363536879120, + "Beta": 6383905752428796250277564758113000210088026463420065838839084614515249744542787137335260156352781909285575181736319584584032322351754147212831711180929383657797703998649286915337866579299046232916374090641551070593243825134167908920863869754204640227991611336164050724277862128297962931418130122432222200446221945291378827394238707155652899647837947271118136644970160275460258175813375575503187073781907910436947950248205911933849251714803901520009543233113807905328953743856389608999384311689693859532053392141497847428716570447646055799043425261976758350155390909248843772671309845376700057214591278670203530835688, + "P": 85841834889536335613758447471256281748366882001349032711909262642025101086297091278273453613453520979101708591671269072160274401411097701332213558207622058770553611412922280227318395510587538140292393188100585038959696491926812731586173105698409784742194604325269610587546507554657591959858904662094646986623, + "Q": 80210114651981900436987544812558274321581729109406705575489964703916113750100954586667417016242068531961234687429634231187988175556180229132745950710770303932973635098275903719491664787553760335765636177530712510154719330402270000583787144033715649278677412303588268129650143785925648822433760211871631057089 + }, + { + "PaillierSK": { + "N": 23490601338909561678561832850575558726884812405653943804649911011749816963601846660627582966206308492497621991345760856662153250993301697575609069520647968941908391330219919279323184667316614275866188529073861802049646638752896985413672191675323131194787350502922020356859165571809895487566955513232296714735176566343559334688077288932255710061566111770667210646194738615112742599112692806318650389600040601158453848509908544326118921059747973287595958562847353552628304515249278417520256357758403456529924057003647836144578988214811244547272745251882312872469476813473088985927927771644309809928122929127461230006381, + "LambdaN": 11745300669454780839280916425287779363442406202826971902324955505874908481800923330313791483103154246248810995672880428331076625496650848787804534760323984470954195665109959639661592333658307137933094264536930901024823319376448492706836095837661565597393675251461010178429582785904947743783477756616148357367434164592757026864399688264877878353543799732900488709808940051816925005714501280232262921315235820697818467328252120801771834688123330707557842703818047183347474901127266719388123158296064142821683649396640871679694415397886438009499936854715186866182033421981071082040269129930819853439010532920921711004782, + "PhiN": 23490601338909561678561832850575558726884812405653943804649911011749816963601846660627582966206308492497621991345760856662153250993301697575609069520647968941908391330219919279323184667316614275866188529073861802049646638752896985413672191675323131194787350502922020356859165571809895487566955513232296714734868329185514053728799376529755756707087599465800977419617880103633850011429002560464525842630471641395636934656504241603543669376246661415115685407636094366694949802254533438776246316592128285643367298793281743359388830795772876018999873709430373732364066843962142164080538259861639706878021065841843422009564, + "P": 170302986983647778148084655559799875300219484383294567153445804502839290936092979168068879052117280450963295109324249013673066303141796890373592396982489903666221430970063608585456860242063865477717643262299856089523258586762259268631644364469784961187976103497919172879372340161714143074838128098748170280339, + "Q": 137934171061633181129827746940153479178292820482938659423412706976053296747597266686055667917451679311853618744080053708902185380359514982106680758228769282267133282024681370158553180924211305408839114948066236695666898832276109259641227177982154178917433866013027648968017171620955959975263735186869637716479 + }, + "NTildei": 26409730782654867095866932276274325839232789871545669928528346987651006049118622730214464109045297973572779748976527360110284557202924055176912573769543507304926362966976563133750424601730756543081393390425901904396680491014167862188513832119806530392548104828327143562391244740740905004606310984328163774343843655330975835708194582962677402970697567600039625209441347642245568764561082422207016047998283319718660517400948670666493389547649722125232981527888149651054292955754223313051227994136309544621457084160848169516258114615899084150087908699696648101026128601159872329596004067429719401219808321396819850932861, + "H1i": 25787470845667828439333194128235746212376382370752110453429873473761119213974826992009845048404136469505934227457654230923200229098325447043637656322304711430889303391018095577612569749451202690690580531438678549244568560845872319149294372395531545389913597349014831139184275332411502105630542654628108421654352780938736116879874535886828041477369321010378454057396504028130374837377066223885903343368846821057545084302134584299897880566762947524317852732517573416566636204609456445024093151036087099799914942942374379479912067639594833735819974633785150165678769707286370726404595818135165251634888060035796672078625, + "H2i": 3064350222899130161846345607400999484162450981074121667593094250042985972310366059815035917267068347999069085586208948876186294977267398684913614262592905359878533576599928037577374440401774523722297196822012860279315676763854039744162401550125551803573359185803797750061259561130563222611587757971417639638352837507761156497391312694070108528324759688242771704183109376594315950462945448741984850259996669874710400899548023065244421635195591160059763530777589780515966472912117106023789491423392738068386491492721413406939264764602796271209615587419095527954072943229861144338557555928412226551891144762697588999537, + "Alpha": 25766327008850278931129487555665656864179172158228979148202079684010161542086645287139369308297623212582828296031897710385636903889779911933246523749843594812044299301213991227119289554119063632717487755434824035119559498750343169564264106431068472314741756890604063848869266984633255680820177932313206316336226067095580363312059300391789672506557327259511274280465462561135788335935342049427389720406239555544186908678247156605395963438333402243998336241990134762298536491843926179215953545383439324212248905551461107666898065351771296197196736686327895801546996032875072031184832322819953359377719415579985143944990, + "Beta": 5709342927292575357919244843023247358537095262976597275416722504722701552065098751505138579827657048831082424600875474298313223119121633371294395553574353717644535570811796838298947998473215512359199926955096778997238585849116510337055696837171835460598227182978440938080315011929395331459856375776031108204757988458500238779828499461043184188883099344040141412131978882415628600909699500223857965973599069661364760182148215671697572842537372104150657993249399100755619960250792573721758056683935409489876503054891989021159788452946133516361421364401303833448947448337115531449892834087998423029120832662999010312625, + "P": 78300870956572191058689075678261348919410556484818210995697564106065811670858967319685144742382879876748683915230533871952651154993826160345751439221863208193464655611309253601704320323646111743323854766434008617833234683294660942706917899252449490428025864524999619404773776554939742692648014585281239451511, + "Q": 84321318715925993886343258356475861776534259689989747627307993870398580813263225829448567081510022747430786745931113631084409442376763729088813227276108297962741813610840210995928154407234253397708649733921253111472909413831056337306639599394442988552895885406035110335332393526994524740983602380968600758953 + }, + { + "PaillierSK": { + "N": 26209237752569703091655317506342884781782712735030728843768874386865886608161718448425410431604757037457737778627341881471795375141477764495798577822327640736104808681646912387939045873787307834428432131050366477664601944159976633210398165824296390219671065251790296394799214717641065373066117829846010913709816379658709186644752418684215870019980187340670275482573583690246044241111593119875568761626467599862861012922831949616446494162282665361627601302424714685716143295991962405952895505628778016522242772040696971440775063131779669633069132983190370111442391405678583257488139744594787054307346519404342294503781, + "LambdaN": 13104618876284851545827658753171442390891356367515364421884437193432943304080859224212705215802378518728868889313670940735897687570738882247899288911163820368052404340823456193969522936893653917214216065525183238832300972079988316605199082912148195109835532625895148197399607358820532686533058914923005456854746067990218752217703325330748196571420651835156003661856227917735465098797953061991520386777489565527405580973101538628038527921391131067164147418669899602938500402130729873583256257319958515483533845575179769505708589506975762587336569275469288264024256097196888051809490305478177972656670543522705514917286, + "PhiN": 26209237752569703091655317506342884781782712735030728843768874386865886608161718448425410431604757037457737778627341881471795375141477764495798577822327640736104808681646912387939045873787307834428432131050366477664601944159976633210398165824296390219671065251790296394799214717641065373066117829846010913709492135980437504435406650661496393142841303670312007323712455835470930197595906123983040773554979131054811161946203077256077055842782262134328294837339799205877000804261459747166512514639917030967067691150359539011417179013951525174673138550938576528048512194393776103618980610956355945313341087045411029834572, + "P": 170738855569493609290601569378800377400466394710066957583002595262164358553117416599284949127184825903953526429233685953900427266964553892325366968757887024282079365447882407541235664564967715160822340863297656079610986727723166548710599031795621358939759386057497658926526085743830354383814465523453030760443, + "Q": 153504822702188600055166453340676499738417275648201201278125259512949684962569579293243038944303642904096324547395186406469011052535849334973939496327028455557063126282620251245147326423893270394352740027039776349746897390104977909685395400456172224454119825227309494942633047894600754610190966835478233908767 + }, + "NTildei": 24095647828292496767198123230203710238601231234383057977171740906284364301549696865180642808431559733272431846824384583390062834330776477791699935847416708882943715313539300128670174731572131533021336142206180812283230960878862430102847492273122764038034717128495523172784100444969902386829263433756036489510543080036009167644248158181087577861975298999671640724956622007075187893141025481704214135654884668228901241511500706564990207746569246240976162781762325266669239747300849548165684665695108552403962777497380154080752181244456003031849898998171022371845585436665686617819428961503568237722150521983172953485797, + "H1i": 852985123265249962978889182982965793742691494177745954833146482367651057843298193408855645826577523424749249089862340192136805671536057715749938961466481248882394835333038204203071242097828082238012896048540506894707728963165978612335058415091818361259553904241165288147668268103227084684028128238712250197479500419878928520132896273223113146439632069542231369632592665875406253114150013214790596155706707540360038898709782854232684077130994530035788365294611044464087770024354893300761343245536087583544168014902933283954766756758467066175649294952453311887474017653941772601316673491750157364637009931891843062839, + "H2i": 9395601261634073643688217872555610910758969585471183037453198995699916438919370408804012761775448607876657557361769836834201056472498711208952684837932717287015357766526122762373535213174978933262958640035389584399150426299350450439251536951240078498598864973832628598633894701983361713600346236574466880761271869364953735640426675884285611697640790330381862576890678959102498242551920995495826526116662330536171590166423948196772285548765160488340407762355047477147988392262374139039385394558722827381704045476034708603846097273459866529101282512764108643495686792885532509151405903588165529067595388114432011429326, + "Alpha": 10850631217907308436434645445937044630525069858389046782177542249377101902353918262443234192404918179256375188513864767195126142585778576909967521505600213466802508822530782501895554589235350563514822053712794849940542124785957973392566000300478341614860425502506438376599161683418676678907294360703811189921134325342073995428949998314596942748684529390518261567647426099725090331930781795083828115442527322173099663977764088654534806695486429944557133200435212962217023960182680009626319974673515553562926651620542277882173629991379280025954524303079762516438333051055878989592222682621687117751258420934755837103901, + "Beta": 1172485740683118106955115531144625863022766762541173913222388075235874260034094951926288351792954875819777051517330921605136521476890256440934771995056037714173349836800767099768076383601116213917869671896835221853958963609385683906380113886191296842928680440633130801099521777243327439726737277854368904169336569554615798640751516855616891088264142082305433062461925603618012847791701059553288456629945078393257824320014396986035034516289393998479215916136450810212786044478778595139915533249274138399782093288690550467466914164593337257193301744645610444518250555888339562185033397718066776099484001292834396699583, + "P": 69003338511845184385574753317289313431561762931560122875634935066490390857304235928777770957781530161614401424836399966367683457695521647162692625884858513375032760660343246433139047806653872038018202178023578715695898166506602641554395401827130014435270062806426838827930227291413191271013337611490177776091, + "Q": 87298847954132729985732114912807284818567636386737355324327500427195170474444308862011029692086931598212628286929539803074548281557654168656888476601829996053754803483547507772343178256353082470413953375736476230348967963786816065721808938144347250283279690937942629111841387250608569547918627887168761114529 + }, + { + "PaillierSK": { + "N": 24226495339008659993347335264605591492361432571130276224913595141570778081189757418169593983862931902246010108037808521900080551557729218766501797299247107138754189582404967009951492413969855496198633561000910295527779851700367036095737947890658196801491826514616276578458533152283839906635216412083742234838852478882332936604066612506775290899826099570759229742367439949008871749631294319856462881632450030436827382325392622098581179464152062182169851107008632929735745959264175086727024384555634948214515026203642565075729254502565748559601831613482965022691682024914400325342768604574705412144612256330071688055341, + "LambdaN": 12113247669504329996673667632302795746180716285565138112456797570785389040594878709084796991931465951123005054018904260950040275778864609383250898649623553569377094791202483504975746206984927748099316780500455147763889925850183518047868973945329098400745913257308138289229266576141919953317608206041871117419270312412591412988694873312044419657530849646836186299469056906849922304434914686803467859936484054256682726422281673627074278447211287702645759316656423237958991563920368438001337407726387974266886745609716235669557376235725674961428819090762433479637097303183428012807794896355353172085982803258113738830206, + "PhiN": 24226495339008659993347335264605591492361432571130276224913595141570778081189757418169593983862931902246010108037808521900080551557729218766501797299247107138754189582404967009951492413969855496198633561000910295527779851700367036095737947890658196801491826514616276578458533152283839906635216412083742234838540624825182825977389746624088839315061699293672372598938113813699844608869829373606935719872968108513365452844563347254148556894422575405291518633312846475917983127840736876002674815452775948533773491219432471339114752471451349922857638181524866959274194606366856025615589792710706344171965606516227477660412, + "P": 146613441659293146775406311866447279788346639511334885504405612342338918665379823097221343534242645561654940572609899384060946822956159682342351807999826840732672919225554098198753325056808653501846627616599539444751474705590553386913308470426456628615501881806105118535876468973261670562504471227142794860843, + "Q": 165240615490817479901459570820004304976053637575522257924920522966688222096085123152305818225239276361806988908219375460371675746773327094535980665695959613085089912197884112525596244046050346178894907367610554291863027325523845249830884961531641434801985536741439181191302342890737397410142178586701415534087 + }, + "NTildei": 25646639870508679890457467827413071715305611680538511450942738572900513370375537281008005029244818759114526769098981057864246448497060625789142998903171026415918154547778876374500212834353649228108879675848178485018981837592615396683434126129828330842312369716930461848064453161128273312406445934598680276206473888777771305800683666665940568894751979233943752709262801902571386688652653900966533906840569945191317050676111265205965831176981126944327218097187572812111773841835222556984667079724136501847642556267150880961901625633982612075044245342388706442222026421139421542156808791536401246140747828266357486381933, + "H1i": 1830436522004219017331314396008833883386543254078574250884702882368390128688159663993320379778524310091429422597552391446700590611555198874718640399315324831789427565614116498213012520385437850767917932630146786866088766487366821410129377640358936343641082682056159898777290383981773682141576989313438439961395765911808110618455073303628141564407781690103818441716788813828578637232161407025711185908096246963752275647515205082947758755115661589723489485529989528882928929949307208990629769015580925743267604334519881767887662872116987259307240702697345588420153293967498614454655396144668514307653999590891132314150, + "H2i": 13207038330262414542645488938480233110924622530759856032421051089622789593515992471476084194187392424384717333212503546132258654867413684285694146619471109240434056433360743618818325523423252686198620622113114376313226156095804723893582353183677428207548595961415785390007536598561557824400101057903769185128477599007802277494072327616961568898164563060117896252355405212430784908651167441231028199138729405681467845664258836973473386063851470201072594658403998089596910196853816329104018096129703018133425098307386337589001595373944999686544689970941023605846173579376115700163556162290095518801047259915723246133480, + "Alpha": 4456246080727343671792277776089192884165217414714493283587070524360263018918687012031662992695429290308016846624987633863904243527668063401362990040589235531774928958606358275610193076374692887768025429396104665048952725738551246146109434522126669440242846038104685777060585888509956097597243904637372314745230509875239733719654175016476353674403368099493173180604224403594541561073567353635230596169562854017326624614141554008576812692317458797967618696342624158319998709143582768197868740447440264978660177008082738517641881048240715921465237967229658611823860758708364323089251626136640074418542566534522003069446, + "Beta": 1873985825268880415609691686624015199210214676288990136267875279620036725951059101793188864911049369567531975423934477206384903815414060746059460099029671684885542289740758865268346189219637503164731615815272417995232324913025656175466349456273139313391382026059026465602218644980411325317337632044907163426096368026887401701348965892910792011810196307997464098678390730345329110563573237061679613120511217769424877791778693632658232521993949703528292924494783402861688023653865274945108945543183838935796688581565777412528193016110397424305177286483714118700018805893222621510862401762657367694669149723029172380198, + "P": 80376082392840646211962204387469990649286850137144049250836188487866569065341103410362955675671767029354887273300275272480489039962565787433306495308401546703190763576197113410916579887108352958898522392118600420061491507315575360464122237434331251280743168942302801369947512248839076831982915398602553424869, + "Q": 79770744937405371197297579512199151777730394230753242123597882727715828233153742983746813191939851847791928006265671569542607937008583834939723699278504573195770388469270509135072595109780726995327317547844521727081714086694939775232909182300343383164177805405757849573167158870772942849385301514433540163923 + }, + { + "PaillierSK": { + "N": 23918974428002212145004834784274437495972536084914640126129092691811480581585206314122643314883721276553348818089741280337056176460321079060418289059803069008354728640048717271579876794960629527335497926031496751918432981913766372904853540608342709934687765239222630750039569582792591016090026567381451334634570159571748766256726493508086784400417894888192328412722063510957527662520135139951653119586655476648390967275124038667319073519102246548867729678576788066291872283667516751406322108491579153804548395631616384779462495859858842817696540075122375245044059140008713025404189818821534861125823104625713824043141, + "LambdaN": 11959487214001106072502417392137218747986268042457320063064546345905740290792603157061321657441860638276674409044870640168528088230160539530209144529901534504177364320024358635789938397480314763667748963015748375959216490956883186452426770304171354967343882619611315375019784791396295508045013283690725667317129516285175450969775596210858550139448277385241691022422999516544377224442634163044538936459221008827867358829156927930863071753416910733441820317975670494266896564669304882121654756218239560416032920717570281025157336655525540816557935409392711234439070459360937845091194059971898752625929496630056015692742, + "PhiN": 23918974428002212145004834784274437495972536084914640126129092691811480581585206314122643314883721276553348818089741280337056176460321079060418289059803069008354728640048717271579876794960629527335497926031496751918432981913766372904853540608342709934687765239222630750039569582792591016090026567381451334634259032570350901939551192421717100278896554770483382044845999033088754448885268326089077872918442017655734717658313855861726143506833821466883640635951340988533793129338609764243309512436479120832065841435140562050314673311051081633115870818785422468878140918721875690182388119943797505251858993260112031385484, + "P": 138799601340356479987321324143913412785185464672990270679770318467455928991077304608438152826514941417409439854345319102254393500447142264334450645403062092615791699561804442952844064931804578361948380911982322481966160864579318280323437774323148480913265949076556335986994604015737135541661285676614811125919, + "Q": 172327400057507837187979762225770708736154653035956097196294159401317284643789509254137093841698517575246809762464863703338536511821282817649638397222384985142287454767102544210168531123295454610534173284493500247181661684228442904257231482013804295252652272210280999234807094862000220332302825688986981531739 + }, + "NTildei": 23754586334013640952387347374181481745246111085139419185419994861368042032810333593246633376964318816724870668652914020603769924339705038419167605336493569157344381294056273339895350319521042550819854211936203254314129664733897642669613681075220690148866177561741599102716017351223553688180555905814547270181578596180923287286188767352472875084439736529797297756828312982446565708577305944270409368170062956319750072756943798954125720976144840856558070632009776431717606793446973973943819115567763353578383343100378732233033056952970573721240868194927569916987196067170771575078539998395448652174448398571170766318989, + "H1i": 20234534221346036946661072588421808447889547272782562181768161817816674330339042787336118197200974556405472594808715399150373800925094932045172085150461788805565660516563506937613016504244928818238488104533326795031586086333742954622296202566122804832153822672656398923622383626507883937480607643774924580568059872219489282941205147400585260198980400609426930436288158850185628848578258566091785890633993376539004965583600097173300667312930251872963833292382572515280503756731381437518807696419874480564198131650248127784402348483414493729494592646398659341663140370212266191423703997356242522335537688660246323788834, + "H2i": 1543487835970251752814319925832531789584746055913807831847746127176653505958363242762364214567643544598469389575303437633363276853624664229421088608618586461781714951119370848269743642627998105361450061072775849541344219530408749231962516080815130970938996831111706048554564536714808737807555109586374381885506733482813006696121363696428642263549755244831821625056668962432789375874064992417978559745218177590864899922690473146689891989362255782384315954959575710103488312496486764986627003524782298342060758254518588820140331659589983066038463853556185070966609266484315049306946305755129077322169739283991219454513, + "Alpha": 17274527130641727665923347807645100582638132473233531004150531666835587027211898217029048448909262519853741954787103841286708212881558551721555126335329553509071347820002917070935507660797289158571840989657321477984050150531134041021765838015763531242726610217796890964100872892676171136687302902777554162130266196495512024354066982429679678707682334965154048262452880475560933558048344979800680009178382929744023684708369215509010034817627739801485829241939056666244305350338905873373223386847471500046960947050859442277183337750794252074572841374453393318731599371981146344736669882346111324919693354521733879500964, + "Beta": 3137833192089211057581401968093597481396084628659032103784935377850492113676628237379235911153045946666430041440037706710797110526610943543866363908821842180644198782566298223784674129892897186059986748895188094969053998665388832965351082106893071689839645887093119782427193483009467877266911405027474961758788148409072533679230296572003923326632112965123831881099941998150596545989958767531794510717626888105682164226356250906402051582978665161384485865476507094196497771741622097732013270962861779251534359184418040517411960015229789286074019625054090972850795250123386348363021280708668857968918106500350672704617, + "P": 76901327610600597922138839108045431622357230009493091246261369440015411670962538261781532809418201887232286751935794843216361717620364909304026269695608182117780302748053114960694502604154034321818845870412651587673617181611830814426571453201890040990140510817548563124994578167656840042875069905647215541011, + "Q": 77224240049202832221228211643209478113500562350948543199161941316146347350459134497508963711994731797136402025334635523381772026064116966011214047696701544595573278145466798723708042476555018190439241890347973606957987019422843122009236867464585390053300258553947202877455472256678318299213488652629523952021 + }, + { + "PaillierSK": { + "N": 21304955020407487197411730288024516332391148670740633630846108959950090449906439063431177707713376695132385782707686953292845786673614030007397087853528983150857148884784678163357971556858029401205387205810196163267797965429564998885228919709670085148999076366900098980094182971031950866901525362592314266715792237919251541746120854651386542745836781288092608721270151789661363861997725029514884470002600003775130171622493200260285335970774262777516192836901576030723130345125560124790955550173314446284971990191379609292197298288614426912748030152595873953922589509302246522747073609567280809439723031027005801569401, + "LambdaN": 10652477510203743598705865144012258166195574335370316815423054479975045224953219531715588853856688347566192891353843476646422893336807015003698543926764491575428574442392339081678985778429014700602693602905098081633898982714782499442614459854835042574499538183450049490047091485515975433450762681296157133357749955617204489799709624173432368034066560721407985537306976052656283985058801106708879474875857037396735385668287883405007862989996112606703973145010667846941761813880485896459135926243193697221354475738281662483144815809170450487019601788879230046084013530389181065492469993292188264309578231651690479254266, + "PhiN": 21304955020407487197411730288024516332391148670740633630846108959950090449906439063431177707713376695132385782707686953292845786673614030007397087853528983150857148884784678163357971556858029401205387205810196163267797965429564998885228919709670085148999076366900098980094182971031950866901525362592314266715499911234408979599419248346864736068133121442815971074613952105312567970117602213417758949751714074793470771336575766810015725979992225213407946290021335693883523627760971792918271852486387394442708951476563324966289631618340900974039203577758460092168027060778362130984939986584376528619156463303380958508532, + "P": 138497336462949434754980609815195633167885334632900676133063918088265532530682489158458461512016700284710034193768483110496071582430789100515330820016973279768218992175640159125169608479928067948151689410590962671301659158534290194051285254625200205047040298028201895583400260474769826196544043665737360673703, + "Q": 153829348379612711946625694706611044535774510643736970523135766260530359349440326938667058738869228696949366092148950339773538408351248463592915726863267057071387725188948172747514089206998983894111349304225321654606007511739235744657541320212213656707522150495682496178733362508134454624022524057887482387167 + }, + "NTildei": 22982245201168825265801027867115038738850624494713405600577345100940519763870290021264156653592448755281270328544503708146716897665358459869265443425134551730054630468639601120232242265841746018152367612787208797739252348658989601911603182016148322340688250020724927709096938877004498848897030720402314279351768737535985841295500700690725601247530625659041925892743611140775186762249707218001473105354928405071818578505903291599149266082551363510148703438824396595411113478753127167937994427989838268152902401241426552594614601420195404882223958770915035969780935004777451536507171909879256996786149786387699792519801, + "H1i": 6955497152353002250359002102740982256902749902340450227310885849735211701380443393631760858999637982526455968578781979795728924665117696881899803737222762624390381177648721575837712437637768873582905778929165234562670312697011705574238422076044078265187289143214724927892730926650383258563153336007222470207492798052452570412345098231054830253513930967562615277833667929966897000083806949845719971081665992914333700256618497009997697651736293941371089561356326478492696458994356148904127559268413564988902331468527960387775360060059540115259383237152162080614780729964435291631541725107674475041473387232781414397368, + "H2i": 2991306255351728643978350943234096404629715511963736949875914933599100218586272385807964150583269959219715638036992996250928565417898897913806335593208583289971685346539841735490315920318003182943396102700691126267522208267560710947455072083929328490121927890614258513623271427469375665175966547505034225007665537668919034942471204140378316067717294272041015381365985876056045063031654490183444245257885618654139159000569579788843156893115704797219260727793431161241391246718637962730984598950719594090589204472553813805323763325795823694885986988927036300235821818380005760523928876771771972406157274523499500173674, + "Alpha": 16422702122488996359495461878024150642809238299615607084384523100657023981286592188567723311780072986693591033988875787853467549991328585271793608626245360928267542729440796265699877699865957428214192791764224465779275376952683585001165145440895473330681936259315472462315462981005415247192326397134840720994744155646500104674724246354821301492026576170927487799166246160613694838042775216181370152894467205231370700772815558770844475287635950973334328215557967915891251922007554366229583704385705726996567826915313676746205473242505781788653577619539992331638287643453867477111540557494209922057188618524458886509792, + "Beta": 2448588344039815217454826054648526699934062171006112220824228801687308227250537502711903182951450318270118339187049845780627061872484353382310604948570803355095266158147638107410378947974500743877325222937829651698630191759396663005727649542604222376530390625188154478063607648766849022745643465978956181019745990362443735959099660003866817062707248611178203411298808007694859043654766437525882780061098087564751335270206260420414443944290625760840344334779239221934464973998025721282728213845533834670974408619393485118762634369817143715784153217446622975765916417269363778490226912877413914977617482387250829642267, + "P": 68522028421445552536812060601200567089243588421450422420878134301295078910854763612281877448421731208836837114171214280715582424519721628693422549093443656191459195460648620544230095566565068840857797880004323163119831034333251845064447618333971352465560224315286154376605678828243717201294146302677562253621, + "Q": 83849842636795032631863028359885768423642107836950719731069156668006425957781674027749846000048597323840531389641536854179734592564735794330866953882300657909384279516736642934901545121113944859868708251377520935249164342025756566223360039880257328078431349132069512238961549382456252455783174442482438096853 + }, + { + "PaillierSK": { + "N": 28925787768477618253605695014020982770545644950879718013079950494124484132031704841718558465324188376346892488386924643838475388813361412455250659964534025281746275814845351637483632675592453131287266305822207015673213779900960967093605821330662832469541934036792155453940303767526945604656887202081663633227434101128720211081611225872423904114669857242484076828125988684073059103073017692780866223402895316442639960978120884350855534961522866567268465651365056662395451245210382420049882455284999786466914979171585181620255852792997039927156204664085202603658139314205808401717777421680166752852840773468261605183897, + "LambdaN": 14462893884238809126802847507010491385272822475439859006539975247062242066015852420859279232662094188173446244193462321919237694406680706227625329982267012640873137907422675818741816337796226565643633152911103507836606889950480483546802910665331416234770967018396077726970151883763472802328443601040831816613546819576124646689480681823250650270428285744162443635954360344208998086548481406999974573132711619919055834582839667675474964704686775750986173846589663918416667830476049416374894140902412484581483317518929721093677157688263904536557701649522768188379319116218071142255775242736334240989155428580378255679538, + "PhiN": 28925787768477618253605695014020982770545644950879718013079950494124484132031704841718558465324188376346892488386924643838475388813361412455250659964534025281746275814845351637483632675592453131287266305822207015673213779900960967093605821330662832469541934036792155453940303767526945604656887202081663633227093639152249293378961363646501300540856571488324887271908720688417996173096962813999949146265423239838111669165679335350949929409373551501972347693179327836833335660952098832749788281804824969162966635037859442187354315376527809073115403299045536376758638232436142284511550485472668481978310857160756511359076, + "P": 177497458296176888206990794836262355597197444068839324123101423260509726358636528386023106636912565620058783633114086185476194563946735969035195370819010964379680514301890636297031273564433255278184680407307755566989142982595901792303003454807969481042352154175902001415169327532094394351722003518577022719443, + "Q": 162964518174740814442871431086341218216088310090350232094166572394553203617418350394893970500559510984469508179327462814429410988202579096260922587366717861182435069956392951003062899915741562025763663726417983865912394433873329061737797910231696745857148927593764115791057608675403876522807912788928071105379 + }, + "NTildei": 25786848596901821069035194162714873401124392587673325585014497651541998581117826929020356693671977667152865903241798541951818822942704815371370090700584221388205516149400101312560538786930343283371400431917681908517110150527326699766194643163125698202246035551041420491199641237067016908079358873975369502163721166214290824779234571545754500972471555192117998268130625711826921226459558200530117651933234463364952496208410308227300762490795445268714161656815854122502280191888399970371217690555143096081210920677933020068353854589882497187812533943081549010242009202802203781110688158529163558352250313095880585898161, + "H1i": 4481824439008030008012507578900462323407515443099779471407166575922507170843483551429700361838850886450238066401154774126543897365436550486334599493781256565868790534378858377693813899903811923148129708284486923639631876139705029613470470079257414680379950465128718087346770172090587555687592520015314466851463690728411651966996811568878949937157942979111010824710807095704412003674518766423568887490129884251524036795543218346929888807188896981195213285743632195585405650972888796251526204177799853469035611825950881180374346510279729270752998073965872494723710423855050600871636483892634345413671982895031967042772, + "H2i": 10676122491799239358083190224932125614134027606352121952287297848314481385717632231143812212433535449588794570802549542443899214495951709083917384447000311426036515517192014153063828045286894456633782419232599654886197244224015146499697210240094583706584526256196625994822540240428346132854143049538756610504648428187422570165273994088741723597395128208437952756982304340400097732657734609565404723478698193536700064833974029361975616924636419815933553076472340281668367157462976504557128015617006397602656663603557148993544899300106940493142755620042543902005804845622814546634648829112966684757110152478490321874462, + "Alpha": 21639601886186547851036251166277922230250317619934308539847786418536989910361898115258325624318780460170741122828327187092684456243570050286514542668274556658555708234419221799813867217575782392956343694791602518970389914306777697420822722032967922963373453436593288301669460578706079576771920052221837685792162357503449873428615181077610146568217409025234225657335045380399340796607666973577619938609762085361696213521269564358729771725678235765227672437730932137017277031134355664768448854826001724445780490477040864136728601306479998642378453553022688056025708732421219166425376663874504130276274273893651288649229, + "Beta": 1466397064309221215074093964241184460785969463354538780107121757257648155673227701156246755664329321843632696823825718923808740324525430950143526524505988159673186631468852146884678717685308795100079279280579535167405159243695723832624028259264451012748693789879430785066341430798321063047711726318687041860919110287737323351269310867295449327625028281092420721587949680355576508873697876440621277408862030654149455336361304181833679535089518755331725992934811711425856355754741344858764596125619291947854503356011623130881842679824060094460815548013521984430482449448023091316887647160646480551242205645128433614928, + "P": 75884160780423116549423613602778314657504296130592796384601701901739848855905823643667996416807985184815534251288657237020793887829912704064525260140161827354277888878561194326451938099044497341158008059372494668585566981075404895318252418354730066454509401445164722870851986077420542413879000797451831829483, + "Q": 84954647754220173242370993199805092833000101059279014261333098515999235729072888709864123247571917255378022968894538699926341790526995031727095504316635358627997364974562727508633928334401437628492907671596572645282493298442283902509916449658342352232669753473010325827285365483782797263347666743955736940891 + }, + { + "PaillierSK": { + "N": 27355471664299672215751296660843386229864604474082012247928364065716029774714705303150786005124716072927149690881758538070552780850137759809565668931590472886657906218187539220786848130698976197283515357593162666372262590465802234547279894935626677477280703794240531464680125357862986939005838367528860269857711805763084475141971131465125383880920599075011650686059214600941554092203451531220543322799853722675319674965143449765009772716143015252281445012818894295250306883028905492050269772988233691251943781452049296879944778001629284234672904994336935606504809435113007947705749752843506842464186014130438057083937, + "LambdaN": 13677735832149836107875648330421693114932302237041006123964182032858014887357352651575393002562358036463574845440879269035276390425068879904782834465795236443328953109093769610393424065349488098641757678796581333186131295232901117273639947467813338738640351897120265732340062678931493469502919183764430134928690299643376517353671521709070879693474970609858652556823685710150898371399115814022763214882216650492922985623828362037422824650143288019117764457684850688346969866510472184967284109450099751303220415359870678430592718486098758335230768210865565849865706134794026385862649244300605042122155238627525826171938, + "PhiN": 27355471664299672215751296660843386229864604474082012247928364065716029774714705303150786005124716072927149690881758538070552780850137759809565668931590472886657906218187539220786848130698976197283515357593162666372262590465802234547279894935626677477280703794240531464680125357862986939005838367528860269857380599286753034707343043418141759386949941219717305113647371420301796742798231628045526429764433300985845971247656724074845649300286576038235528915369701376693939733020944369934568218900199502606440830719741356861185436972197516670461536421731131699731412269588052771725298488601210084244310477255051652343876, + "P": 157298972594787349427105175697927342559427189124298032609237304302111568505513853020385132811680804611375856097421082369018732000735396525101960654834681813728119481857401520805597229656264212980634600403742659784247617931325349935916187161132460923000643787995260659511588087624746222581137402178406103524063, + "Q": 173907503736653085200982871285697151411230666170047539802605876337645780899706050154631760223739617078097847620065643321145391415121042688943955442614511104828247668150559601310104324431769975664868350328565280234511723098106417628295181411473342983772753377529694516468863176617550535638738134696980301215999 + }, + "NTildei": 20875854028258839497257832904161780301947943067608984844732547875966784650159031410033074774122365905047211515254762896479588633294619483835977351165875604822412433145113653066343014178645649364084951649360710609037794658021410520537483045272236868098371828009367288100317607075629440144737060950567022831519822032632019682728390714517581088613373573116342122266735499977520707004525286365066448915310900763328817492722503881150358202074441067255135522131332329174384528851020240957474401690580622790933634869973136619801359840489033020978286561578330666923168665281790224003303677411612093760014318684616917849167261, + "H1i": 3274534278900393938002960874934247961607871473106777527720932051223407016420234223167654528943484751648903733229243045961065161489742443005110343785515581413137697763987482533173245412198624116588784627589113700230491291246586487931124398230201286498358983837195307636331765313885680173646444989410048686259059173371375205634462822497207525967661501853297821405894790267845254932924382054984572654780691867227675100642332072313312154230982361493179515196452515257362137928224721790854337178716442945641213476542060895582683281553297537851691166320768417682914057257408664922301780827711956163767190084649504182196661, + "H2i": 16049958866507585835384815005788316538235209706039409972931027027229126599954328414424159349841129632767398429586294831191865053221269899935979499537360938524423527203219499065050630632214647665009622593691292984617984319962062280580769983384664093202793293140049471218509331017772806500175243348065484855765254052222110265634711515565890546108071508931582248915040784157013136600141836331021838596339861326052338101198879257265809134726044554946078420323323621466697291893460417416647495606876739859688606939461520339236364122681516756742957882948632996890604196093637802132307350512490514330309497445841728301286663, + "Alpha": 4434289267370096012396436893647787722731641043304616834086640538428385255968951510417337570319555175328428083727172073245070982135888260385788551220706361734720387376942830160486552958160479450332120007754089793739536072576998600916715993512870507321275621885538201839890139768298781131869596923167041394891088069524526643520800471771786787861365518573636508585867906135609845635973204407036647425010921891483377641295983518633000849495315787571915381563653597906701624676326242006614928567193057529269190319897945013126073559172779465772259234741369048841621573740629348489025719106008532290826782354170319223011628, + "Beta": 3107991538265375799417868228604270957622162607876641884642855185351948081192617445072967999438461485329188935028482582031643217267577544895463843373008307601508528082892465829053666268997640901798524817389560112785368823768064459069602258978166586696443726889990258422866420413398327195692339661075749190849517239659478016925226405142067270167956375067976615972912258649546798343214978941315289010038559871463355349263575348736943413600257861674112676078727772379850800071526752461195181364990123423978517235961138949518685541832414489765513022801825475498674182392048327863176234872508293722029248792632316019929334, + "P": 72431700099420495489290356213790424565826156367436485759724233628452492647454645911479645836298487493640453444729896969297133519021713217646273897299473103984657912272167944404666527428901464713351154576631619597266636214236908751251030852709635247388672511556963691024555082865353925816919364086243643162469, + "Q": 72053582891207951235328030778916647825569046331117922843077866355328557259164752549562909879642408527466467379957656039013395673057558447367978410440211531304340054960299632830500067039710361369997812560379548483052626470287658682358214233076909929416803548618554896279293996839367966290776759610887390159899 + }, + { + "PaillierSK": { + "N": 27031878793943075729130612763238143159036556026966168238297210838055977134496375773671774053427328728163773047450300753405588197926530962193042353856133247107231446381777900745211505608168398887801093805191133332885134264932128956385912612060224271765525628185622026314614945535835927331721054010711939302016923298107666454724202564125733901227855977219836603772181499663238779623383670377553937250483575824202848407520495336621147584061267028536185613653404629493132100142370212370686909126012976561693514534323945147360055614501453387793858722164623966927880981812086571900895204648488966346879677463741631929413261, + "LambdaN": 13515939396971537864565306381619071579518278013483084119148605419027988567248187886835887026713664364081886523725150376702794098963265481096521176928066623553615723190888950372605752804084199443900546902595566666442567132466064478192956306030112135882762814092811013157307472767917963665860527005355969651008297131398353397351224765510032615664831501079329850643624501720540923782626099365034574394959517983496833606006474012172426670249820983590878735625790863431668052228676992876527331178429066754124949388842247494257044360867417564904377689749883322740922633579299555183956209212054000641630291727717938818562206, + "PhiN": 27031878793943075729130612763238143159036556026966168238297210838055977134496375773671774053427328728163773047450300753405588197926530962193042353856133247107231446381777900745211505608168398887801093805191133332885134264932128956385912612060224271765525628185622026314614945535835927331721054010711939302016594262796706794702449531020065231329663002158659701287249003441081847565252198730069148789919035966993667212012948024344853340499641967181757471251581726863336104457353985753054662356858133508249898777684494988514088721734835129808755379499766645481845267158599110367912418424108001283260583455435877637124412, + "P": 158671274493530377224816277192103855343202897337394546746947808963385749199085330655872119404315862621358502913422815336096106295338535189792317632025858204119799467506574889743771399315400167720319993697608401824830524008994030027058909638927954982201083401418560880357710318497614765998837369237960958315367, + "Q": 170364036466129644528216828476566042849772163839507938185548413193546308932386316828916341160223994587822692594124496940198137266286526164635824769797044425676196217509651727888475369839442885723295762941841757021136368757624227958044433025929366463834631252068900652625075905883350297620256639067793333973483 + }, + "NTildei": 29161472028770218739704231749307098674025680182744446812821516853332700577073933126594191044613078467833455979012724145635406004812880738504987946560541961090115401375497620071035187905034534042654673159269192237429807861262210450976652631684888498657351392392002460156917054741194582616513029006197934082634517240393734271279161896031315097432643445273640659782922487820903437611589929861844709785693640643504761186856171986762726983988999408341749901146535080901906214237786994017651554758810086331097884739533344931007861776691634046308889082929625337057628864542969610018462651464385185194654185084809622599692721, + "H1i": 14570670390536174039529319731824161100378939326791232344676722511517410009236493914871398153784114105487498949436521311119573277886098627972580809530198317510803339261292065814990810087709272162209844966008846381890791190662953471590527995314137777079245025384687569801674570496856438571936280041651347689248314889446782757014575350623005528824285983106358728988861114435045720597904001589180168545660180325590535125055882911870233147020951656314016498058008696778192704695800183841334365002788118175842899187916130668695086993739026454763363130289997616740912270314017664921065205451609228525891707375127849333287419, + "H2i": 792800914287458814598227944253986524940385261255528297578015957346253015454316498175183853552868154828321242509727757029330487017493056349040166740726531292279025545323739726334061668031008406538980928824443968957660162866385913688681703145406888983898799055700540808018064563812367592313431320025256736957369887559713311276797182803550331971266365838027278095909290235826684125214536733189008647594342362438959749414700100527842373183968257215608611533896375953956528161482312395886638696689061870112149171329312168837664019406322621879621213608845758084762291666761599208018829400075701761641062437832985123044811, + "Alpha": 26922096051181872125758904429596015477174321698463279424387269240663696575222178511635821726831831583365692233524889306936650539149420609429862748341392355568629564766255483150774833963679195604052127881522733702068986214006859227244116595570300880121192182550706131503527902709043168819586686237366427160303907591665063796473941144417108553904666461980292390725459020415464613378854680973171413905213736654520767252783434226687883986215938805086178666846732721710107435760461060421357106384028672994376635824639823369022482547890694900701748350488862424205654276615285673082814647572220803569899888042221396973369465, + "Beta": 811331280765891658575051431397759452914375589400483564900894787588230683064550258098055193253806734756428390366819746746069430438908156944642261847114776657113303721705403411241881258306585210664380848532151285992000485448357291076485959638139238666054582742861843509205200722188630506997654820530748097961750667168402638590705919951438794459075383204261557725793892920057751914460434058267951175543672461229259905106237165259709903214818016093484405079902398807403669043052960278569619386433676184949870740450451140323895247738680146870148010949394616629797462230346791071450966971122690726013248138314844696220606, + "P": 81253739302343717672487260874466691188076294739529614614992151320331800029473151087665101782296399880588047307244254457267636586985815491133851112475025874050334505090668052296364462258400147762164000585612067577144123399086048428282929964378738113748536775327025679249504111527775783008234277878888051938461, + "Q": 89723476972120939501297441215074188098574203211681540689623793893547759597752093036158940810472920534965966255351900240985497305720709771387348571076832164638740066258684307694117990428839773904247795904378396405031323870002466834557738004012508014744932656069034631255149726290587851548249637526873252397313 + }, + { + "PaillierSK": { + "N": 23176519199098314473440748640309558297646540572083426550697025492666593864490201106835029700609695384766859205021975913517745538221585575214976064341851145177291305307313291530299454994298621732552418241651073730398741796697485539118671338866697748534540173531090830591646578083857880787938615662796869394507810284107268824146740013478664246034593131316352641541283652975533674437589220834645453420587314472448983247948909487739773536197481170325322550210472496201442507734145264965693181466118761163263506598419858691361875701065182497503959811804748440434435933186538162968134610695809896753112299054087914463991821, + "LambdaN": 11588259599549157236720374320154779148823270286041713275348512746333296932245100553417514850304847692383429602510987956758872769110792787607488032170925572588645652653656645765149727497149310866276209120825536865199370898348742769559335669433348874267270086765545415295823289041928940393969307831398434697253752230004761884302600592951565341860685264172715654385564459604122080692543387172826721662157407807186453904149112525286239516320459445920745245504279138328029456592269923768642353574864553258088718254706200037004458570483211589926577616174915039640463113104691593839201992299539829965402532351862311768554366, + "PhiN": 23176519199098314473440748640309558297646540572083426550697025492666593864490201106835029700609695384766859205021975913517745538221585575214976064341851145177291305307313291530299454994298621732552418241651073730398741796697485539118671338866697748534540173531090830591646578083857880787938615662796869394507504460009523768605201185903130683721370528345431308771128919208244161385086774345653443324314815614372907808298225050572479032640918891841490491008558276656058913184539847537284707149729106516177436509412400074008917140966423179853155232349830079280926226209383187678403984599079659930805064703724623537108732, + "P": 167249952878902168947645601325799133579967484581733489610618546363587785665833270502118404215394665467447546498702515443469102554556509485808277042389735373220622119564747057217321473131984494024350169346397463387223084005147144554493768554419853372446969456907092816888858469377753660245617236068558739080347, + "Q": 138574144866153372591181974207763179642635486339599280544115220925925266836613218489891692057104192608627893151981921723825401002005768998023782159524484172162972430040670371191152843257670153061719919661061153965735476093612173096310810900498507781062737520247882472841767627352483162061617114294732187802743 + }, + "NTildei": 27590753261596015481865073917256518970445332116891062415135288673378594822359668885192228834615984492671675028015727373439959117019691410515637860359925476501012840960085302072027873333201869960351524315487308508518430963997416614298635396828586569246534589834736926011057208550995063525340170616139958834057137689101502196224640728623116042872725480109207873787704691958286856055640747472754741992265050028062641275767673512969752426566948239819617177028149281205470282374088232283159109786669264376174565202528521722255536650689343351074814798475168380738799857043448512563931263341885549831328849904146335400683169, + "H1i": 3570543848539734312515513973206483292550745653153644316483496061554675361973711224550559460783091481415229209286889530549715550400898897717301595183654039077585523189076523210867814836355937376541278539558865846083320865378602307651504601261941125945190144014444620667042531150044197954936840429467271107906513206869058453562638569806132987404508743244766565779446798392871379224006092614273927528887395581052381902942686322730032550745365928790839226647538498584487364212034958371158846078913873199421909552470568656133689481195301546513297202544816320733007036366529762885113541078606184805803236248020674404888866, + "H2i": 10215181024519776296744143429258863093156099178145110406603351943792428344436618740099828918958908409742829600233915330710324920616549607477579337485319061485785441790583535182766335567049616841002248347114110914060966383232348101894819790306236457987098459047404661444024051243281502214726447303006280331576426125798121127803196663786582409175034902520720527169429064719643553355255838626098385495049738542708761914021855422875602997131971182624195016085397879172157524940432007380158841243459642055476131551563529947903150866767210311455631303111458684222872839489387310994010362074729062272345425959206227527070686, + "Alpha": 11958790108683247358980195872716462235549860779348445269952336827984767300783138872276230860344635309184288975222640879424138514896724032346761361250488954048462902519389637871247005637390837844010213496422054123876604107634340634832424238601617905115953365534300411102006565533171075225063496372069848551593965283007004503633070049633270566280455230034313081159265501171475579741976553428533709608413746653631141882909515320650059423180786051892756289648989667469445820579316615988959131734619211154740309496240434757778549163328132354192310740090452922336684669312060092793409130031641073256340173545167347827577009, + "Beta": 5846812149031014697431228142795667876683805387192994064127051983268914854218563312227656136696349539440175961131760914983732526239513014475279460294254220833980705167890974833270969714945569113674619240181898586779158224227067593014047167691233847313916090733553202906184038698000452871724556419631905979897910540625295131063746315365142190086016062418775947406604885604810530461187251911371947796810339208677961481857971462468906409004139213776425806301911056039192659015226125480405642641101635783026476584021328855528893946159700727807910729564270896915370733783458019363834244453152724317531692853846421592010705, + "P": 82064494997940979838036971177384815418179367288650897634197049943140640584035921045552117848048729748430332449780832982336153925774710148655899894468719889349487229132915704429515165441880502736844615638585262096402154314546356071543234582100741747115046954616498352966597718044177703615950825160277592340021, + "Q": 84052041209442265110760231510923501290035117659129619963999691739162538247018334926444820192434576816224385956079766914251649842337019665497699794251440354748128644305272549984765727417535005933464937151875859036166023989069042627609525495054547601398134176714992652491306666382651140496627491753973239258641 + }, + { + "PaillierSK": { + "N": 21266917380121412832720277891977216295202824379624987819968149672847639361511402334307194012758550159406504625632976294503459864182899320201059962480092629504616996190017330881057659085300078140109095828515177856785122951784061658504060206202594633881870095577438377566795373190924549719996791966479779093218399183853884101646910678959808473684287289456269987188067371037025297033666729506142693960195611693405909758957852854745582063996055952305847811952617365817077957595177574573882324892213215327473929147316587172597654215768692434258157495330472379723458918500546028917665516409819784298753368383427358333598337, + "LambdaN": 10633458690060706416360138945988608147601412189812493909984074836423819680755701167153597006379275079703252312816488147251729932091449660100529981240046314752308498095008665440528829542650039070054547914257588928392561475892030829252030103101297316940935047788719188783397686595462274859998395983239889546609053347734213171560623900050022029197569553140835954969200493190038101385979863514282039441526054431258071646221599527014345209926201034046361578385624125728622497655920774193852688112864291011178989274456720037575069791640985439031920810946872250822273537461974405612000720084103952156994872965403882443215778, + "PhiN": 21266917380121412832720277891977216295202824379624987819968149672847639361511402334307194012758550159406504625632976294503459864182899320201059962480092629504616996190017330881057659085300078140109095828515177856785122951784061658504060206202594633881870095577438377566795373190924549719996791966479779093218106695468426343121247800100044058395139106281671909938400986380076202771959727028564078883052108862516143292443199054028690419852402068092723156771248251457244995311841548387705376225728582022357978548913440075150139583281970878063841621893744501644547074923948811224001440168207904313989745930807764886431556, + "P": 135269379436610031009339988917998764551549015167000221670402477566033813177188975574846909468182533031549633387324597993237833725973899718968280286658340582708852798634007417505622575704987996056701242499630268151222748577249251933634199608534028296427721359681318171359151968073634354602062744595800546210503, + "Q": 157219006021148494653538870846416524596634159431077027995982179383060448529813502003768167675320297858216833127329202723653810417679984494156374894710773777124109484702018768671326090779645309059249355903516829296291883909472304260681673828193849782484122216915899522304924273538245630161559708023792900956279 + }, + "NTildei": 23233458509227284185243128814732768015181979242278079472383075879758044897151295119719831622009733299550452846543257724971457163667600607351085172870433645910938272722342808784490602144385821169420372857236214922901467484119080853262761257873155943185686322115211549086080023030520623407102079435384925480774356634350795788370033442456312870894322517965220379878947489336788369845819480370388558790624199561838182116604246026065772728515356203582547220245903534914225699658040189511201539868926387335747643362673269036758751057988106728308583979276374390952658318529836256172994194104498466931431957151513615836733877, + "H1i": 8895894383591380071728846514063015196485037059539880432458177344031562152443461349397914276397793139938023303055107582005790716873478881925342401515466545610829638018864329163368515948200252781444194370193666318401281489826353333983588791442051726546588558208160099332266215448972954829885174562551282521197033637172323034641635917613466904523550513049670799575592244715720325453070169610757475869514002460648103952716023687897852710905365403140015339484222071980095865034712793179585070531464617221568006585961276928369882249129976023970091266423266291050242475498162487897313898597955941006359536247452249334533826, + "H2i": 14177442932827383415103121267661501035183327554916763510692838132230868838349745684668957428714865568597687463024801762611058395433520565265361882677409559044857714640647125674716502623635836097469722616644149016922267325557168532852852469889368336416108242847581123069659648504540802410743741084863900064894463538990632537516699805949839449031259891510590312957638963894635771565782430614612890151583871039525129008665865019748056252641678443445061017406927760625768107885748482001712125823317770749732718994037857218169212241747436362404282699047985558962047461544266908552048448520329100868945750783273754830603239, + "Alpha": 19617185446618458843773140700401185947254296214438215880218353697391045835169061040703736432403727384782522478895664728308084571570419652892297292423649199649471673194080829197563628625221465439675802104076632925423940062020057456538266342605414392259743205505299435432456149950701006822343118272178562540064853907685787739683425046631837325525158912879740921025772206733075168805878231875794877351798039299863052090309857348087831227321822403814092524817329771274737240754327469208789173719308329315866922188819413819494006820629147221264874487321458167776753364993354313361211073634163685797968913254401286081749310, + "Beta": 4122395702598083179295091932218303594228805878931729422019774812289837244384207328144035108722414148564486459128020554929566984145284901496486996747544736659567428989995335867129886524933775344903623088672905729069092541611658476946581539363425576744570300845319131806360197695138471495200293089710212530654683250394746277488696815751083539655257044771597038074383920384203775525151629855521250769210627560674019573640219621697396780431370376013427892168582376785028369974369762213615586019032492382866306054585420663195977147313047881371798949519054648653947258633311852776461730438848351157850989875063943139424764, + "P": 70321095922550154646142038711735281562428007133616394651605572025598807970695270674171360429342160568455147345712313568129274635752794557529994346545398505685329402447661270506539926145942679486117585462513847745898583194205989159874612511305762929936984466401786062806375240436855393407752669559863656363891, + "Q": 82597754643983426681279282791972008328751232419481652023033962007623106852437584905674527871079010317472853490210863417563326516328551428139282143301311609113044739945175063834551869335414222256317430245144962159273281419366424296150088309041563714056238968259483324029490701030983239770438480687692382491009 + }, + { + "PaillierSK": { + "N": 23237136416651021905534362410455016763738186407045432595528243606422292547894044586919798268403688594232299884353541364776823476068743620026851307207952654848926428925387176781509788068214000251805152657341923306552534057070219668728062141175234242925873260687770325910940513138249487546975315130805974597038990925173267114632972128307579109760164601372665452044109555246406756416134029904451334455535019680701779741833639099292724779144831368388023927580404894720920251497007373016524411327527971509916951811003387606608371701565077533607282499628980632021670783054574572198498958491560945271621660408644209032644917, + "LambdaN": 11618568208325510952767181205227508381869093203522716297764121803211146273947022293459899134201844297116149942176770682388411738034371810013425653603976327424463214462693588390754894034107000125902576328670961653276267028535109834364031070587617121462936630343885162955470256569124743773487657565402987298519342889030556511940099645203990336652689282897142863775561181186596235070980032410322607879722003916841194333107133293786338982017220679782120919415413135318248907830648023424845477533773828191666362126404598348803467753866294472734701890753806946722646936621415276615648309999000633134439445739140781134255238, + "PhiN": 23237136416651021905534362410455016763738186407045432595528243606422292547894044586919798268403688594232299884353541364776823476068743620026851307207952654848926428925387176781509788068214000251805152657341923306552534057070219668728062141175234242925873260687770325910940513138249487546975315130805974597038685778061113023880199290407980673305378565794285727551122362373192470141960064820645215759444007833682388666214266587572677964034441359564241838830826270636497815661296046849690955067547656383332724252809196697606935507732588945469403781507613893445293873242830553231296619998001266268878891478281562268510476, + "P": 146127348095271270017358025397766836661316420641327711046696021131699969944846619852568769096783819575249791192959796393669798999930465973386960967337807903472187653077812726357018132498562937825113680094090943439533898436106853856189043526479633641019428818294359436992886250481638501451852716218324498978103, + "Q": 159019764058819482755479874200669618124719157738396781940496852082586304229118463953549926994228027444141284426412715326377016110459542850395127782240816180950248182633513440476438127481752188759113878100099965561902295396381734281689674594887104935357480993449659530209452243078040501290916214144322265156339 + }, + "NTildei": 22712704688619635803220119456991231357411305286797581330897607730285647842774215580942176867209302657798978358761090312064259018366850027662393433967906123931646435446126273565419718140244850185024562422349382682999135567439325659338991658547149202226275407220597399004633897655597244648010317241145601568753121671030525774431355039855332984731422756081010692547130001864257997187767889295880006661178749668623015929014294433988485089277025104676728135301592688595905005621656436667083294398340088239303073150780934499081257458412286303097423649752617165218547865942931741165907896543562900959470036747094236046611857, + "H1i": 22330289651865458499079405278275139668273138438217226657909854098980391561817274763914542876603707812869932530024126179999190712295580367033829939475511315939957921278612623929564537391848120621258633410084592607144846951051421036356100682187923928442919434979295918435830309803268435395551232195216718505097635723812762825535107529931929952911183232633363325538743522030720678786127649678042197290535398718343569781676652797259381155960255346550972217847712833447349906375022608176333200872208862115966228769623026233970178166919687707148107107984571137398670623354299940604858660914064746374948143385468947060361927, + "H2i": 11166645518007042290707642205350642279293558621833553364395179926087016347300867937388340768157733526667519129710732650397769189346987515618944817768088444793901799929491598297917182866318876608138221106415122615472353702239298942145587020155417009189990261338639907791680053503360481537631589760341700182325937418530279047685954463133418865683312858489602252138445355490334701297115923527980293080360579857091553090218213168428145989651857248730872402651164944687476515013767096624419173195672843867953811368829776897270865700890166577534327260493157807435481270859057259152297602528073279252857365951718103038785336, + "Alpha": 21961858383430729091595127692376475246546916975869202990808183977215065492011534294886426450553637530057898183422563486094916517861513004816886755532346075730958705717607117771680709611046777089973684143274645933433855092237938614435122086902564252366175120933300573431093221274482975043395770801252207519102585127156669202067950816095365876109743000449215383843100413510237441480313149172786152327789754332184875892445584843869351183636976880680565084677780863976167501786693463080029325737656423537741781842000140273921605469738871758876652219295202507648638793978352752241009136321456338651173670376780991657444817, + "Beta": 2757595113359670333790710336612667617879818460452997587240341098135731490553893058016602610967837191703063189630525803908840728915203890632812643827013964879029727815984801545920942611974566803489141992436196041449384711718225860379178251340526177581675733086563388745083502861701635309950212117769476413577980714700707530752932731097090053729225801367166061182869949264229043282302284992700060198743000157010108292880241279301613134198649103235298515338130387058399545079158125371414055798339852886338281667711765804934382012474001563614669080191486510832623608322723180161662317546051827900960336058552641940908373, + "P": 67428246151895955479284887615059966758025997158513242025696541556841999947828174899962652920069213614561257664920354508167828790675793030179010666667895583102534862129325351996875268621987188778919709531638955510073033845747571838129933516469548675581796190245101513298351453759472485945310516453223913592731, + "Q": 84210646074994334032000088461783564036952801268655547090802737462410951128338769908753020419351477222387670374980338303600984101560523194774539349909238793549844324960901255710238692906624434972844634821598180403975996223459824594557364427513654761835902198906180609556171557344102920227404278545001812613819 + }, + { + "PaillierSK": { + "N": 24496882373782215488032450173562278698970026594214580221734744599892233151825253846546334202049482263310843653710368698034313961511135267274276704888914033687674623502373800229089726033158303234515125091898153949212723433565796415534558786472652621533597057820004934433654138974631630100729372137373561862500348422181759354732482264892565909034569927029961910160461701130255234601962762730220157181748735503733948425455961103969981742249576057628393644411021579832453791076603742644532727436643777267793325577935832829189826308216829189017175147721629935225586029187553375364800340857393131666682573879031283908535589, + "LambdaN": 12248441186891107744016225086781139349485013297107290110867372299946116575912626923273167101024741131655421826855184349017156980755567633637138352444457016843837311751186900114544863016579151617257562545949076974606361716782898207767279393236326310766798528910002467216827069487315815050364686068686780931250017161111163818877156124251490342178017537404893202613866378749461704204777721402993055155447901399767689819096966091519236306691325049700917024537566861845538973134240678335550232676593824301479170190097791253940277181652090695258726068730333870606020185446293406638655658356711302432764469423745647618795862, + "PhiN": 24496882373782215488032450173562278698970026594214580221734744599892233151825253846546334202049482263310843653710368698034313961511135267274276704888914033687674623502373800229089726033158303234515125091898153949212723433565796415534558786472652621533597057820004934433654138974631630100729372137373561862500034322222327637754312248502980684356035074809786405227732757498923408409555442805986110310895802799535379638193932183038472613382650099401834049075133723691077946268481356671100465353187648602958340380195582507880554363304181390517452137460667741212040370892586813277311316713422604865528938847491295237591724, + "P": 144095684869385857560297441927379842722987643966671405004091125502981217444402634001379441555595062990945994097571463892360389271998665223922482028405740276614492796613139211557560743781241410304494760621555608283874693682504772578779168928280059363088809982020519652431206427338373914266647062187627021358963, + "Q": 170004274562331120609718947657844835811864576208833527724852505828844974962917290232667429297337641207622793164457457039148739594927293002637113307482115864761352011509246761874701339674887254530490437118694713025397251230143025920943841332682134650456848312946042435057817716632152886886987969352361649584903 + }, + "NTildei": 29862037543484952558681533632486107029577346634993747671661621732315773043394898249575367167534744049795361736816183673843493221627756737888675359048632486007412071873874191405581782623055684662073779709944130391228463180465843133868209946736860281706147469871512574816081813404352891487728540293472347116246324635016287092435201050674756458241428310268862644870205513923066772876901605199733269149722119724131595139817540907195040644328487324065283993774397618688125322867084551235848871862295685194314575526060607347196103388717633133049034857708246997247540521042317763884975617737075333143809140064859546349264121, + "H1i": 7794087553416503410157576487891796343776108099656854948603888163021923408342026737929950811852456396463295664455646222957147362021696990426625851057909390669871325482386435038609527130770799531131018679059021584005665323921530734020519863392308023065415645578704067218273369770321333945438342328012754228190305359488093501507859211919848808133414302590732461528010683698650031992752536770118423886553668342827114136841187167777163848805920152155906933591477147239889316945781287105140181545092814740967688119815442386255717885477842254255806094559961702022061009738205620242147070096906476451257758213430644221915766, + "H2i": 21089939939836125854987704962720414572113596622369721605059131418137463330360141851437281786385452377290423641700803611395479869735165566144261360500961863729181778491546398348007354732714063399507272015199249338921387801144628569123632626588614830503597631958036150565200901782101482820540633202999153874612431358599877359585773016585875852796338190907505615152429661521817732357291846312534032370596477358290834152131036825480901665364126106203658486749382186407901605815260638904026146698182766227858757805020828769158501200753662675682041427021167734059932648036684960799493850102989781533107645465884770372429355, + "Alpha": 27081347072386932741856330082853614577550533343760366443449264882357135675497804274546357191676177634384333821824071101400903958794075810990664453840751133029697733602561827699346981395444357954276054276517836982476136035275164467707193884334123277398218045435630065712604817138388431417370969123430340551076977359203595652111981643842485118571262001967284906887187527120103837784994127387872259609854145100778909139770870414995874906504334297415266367235783382786524539762098969446330255722823859374767405622384820899003149037624051616053952038301005149922975855712405681708888817726414956238849794572742428884301248, + "Beta": 4345931347790553618267207449265994092796603174257087343132056425074019376624514887258300326674208038768851511801248694444385843202480385806690332906111850696401460091521535549847893909886793176067142066814437556645071079922773354789940750000683391043307546645066856972595566199480407059908643225958882948272520827450465543712994205521958285971047001157086803121519435431562128593575639583142785817962290035163118764268731654613043095028268447464142489670656862672164057310044900816318195781292408104948562590881769417453536901357676005506861135052577119451551830132536523660786277088841355856276917425823021322826604, + "P": 84873638770231469695007521203876231804248075945680041052510635761887278978219018356508549963829074634811124205961682917286799874639041448982265063532571257830925860784426224850454393230512987612060145458069471189432645371940771105499110909180330740758460202289637169331576406328102216584110664504278941774613, + "Q": 87960284182957482965918315700735999427948310409362080121034470552002966127621188581713482431944286761246864981836281479162864092234657632047216874139030940846380200290182617896507710347948292114957536868662153407688712194790220021010685669576565927315275090061401556577342145179573158019622177800293130599861 + }, + { + "PaillierSK": { + "N": 23906516189589131148425956083394143844553479971531415573907229725977752213733291828081420613338985242222654385259202035542743953550898506435102410822474022599854787463078102462893910472834890419391118731341961671380692374833813708901445085741800095775208717762814605976541861157300452416823766666040850940211016833608734913194604073932372836378740358464889765433136491987434679369947069762783177740219725596641801770332363594018828521148097530944018201912976893899261897470436134815905355728379464673100704975776680885556748864120893893105265366058628577191492814140105593287775138491493273091651057994769919202730637, + "LambdaN": 11953258094794565574212978041697071922276739985765707786953614862988876106866645914040710306669492621111327192629601017771371976775449253217551205411237011299927393731539051231446955236417445209695559365670980835690346187416906854450722542870900047887604358881407302988270930578650226208411883333020425470105353197725588610611236121466172074276389845108187349199505114869087991675394991520283014501220892005635666801037250445886543724505994907094380583802730761544999911897505766836038345603522010469847325165282563407814398168788657880876464153442437288496031579662513072530794061402950000323827048682248762008459918, + "PhiN": 23906516189589131148425956083394143844553479971531415573907229725977752213733291828081420613338985242222654385259202035542743953550898506435102410822474022599854787463078102462893910472834890419391118731341961671380692374833813708901445085741800095775208717762814605976541861157300452416823766666040850940210706395451177221222472242932344148552779690216374698399010229738175983350789983040566029002441784011271333602074500891773087449011989814188761167605461523089999823795011533672076691207044020939694650330565126815628796337577315761752928306884874576992063159325026145061588122805900000647654097364497524016919836, + "P": 141564547393094764303864093307308992732791566732082224151369749677408500252568116652740812801534528638688013795486477438637207250328195572741433347506557594478198675670433858049633065407532373383424655827847063898866290502895790663698276366745743210751052685278451981437840293730811021661434150601751862950259, + "Q": 168873610164597207827966906721378833227876681782984809974892499581287518904518605564407924976407056731780154462376224807103864885779521182515600960008813214783874999754167285779031455927911360022629989383707006029086236040682340688638782807008256988678602129800996244749175391862461422335526479670643322860543 + }, + "NTildei": 24752031355317329501124445245299499109867632270652125649567231081088665144534959646938874511638963593645398981264846892895434875195144188518476198244564737466064860745291608215199668426310610588179116374469142190782412595522918640337947230461338616584436571727471389003275297026199129655339708049617441868866161100996611571633736202220350269050983156859896816752971686345225439882870473168960299320088740963662205201753350127651015145376295891396019691826634983776714797623856080342997031956395519445793177105802930474063801528553485738045092527492821863231067227540502731646429636115933411142613417587831135542331501, + "H1i": 13957028928210741256105162811408092895219318725722734127648519682310225251061654327708116510130967931945457375118700349831992404911494010478819262999458048714513649117181942928804888134369183790393204345014378808916224755634490033398118782172722845740046127043378237642731580203882669977005038819530511480532496805935335381218544002954849755132813447473995813853747089833320323214039659891433372967743680331240827013294260654669404846537422250137381175011807846193981896190539692198202065632986214585729761518052991105733362852229708661019243387433055217253292396797720150617090576695621503168029990050027816047937112, + "H2i": 15752902183140403913249767176962669116241285684822865920368751336603165771448407341233452106576792336182302163734730172773492520842298554669264095294150642555907291198925204414417837392693535062967109655923196281577185976216524781194896194073023053842955495073295016904546059757447405238434102270601125217980140059320946078564584649670589856050545134574039453928724885732468114975835355280265032178042831726992499586531551475109069369555621124646652558123416155068370688242130991679413852403408970455256557524480730148919478956349927485139509804183566916549271390008320247367640997782040491920972529565174114929839481, + "Alpha": 8392891359308598352321038851876787554985365031665078500400971605208556500896532830230637562043821611141580458863266988696170008582719044918743153605746682255391552085191977137899014175096929156679413404210698313955983421438113391803268846508706208902016342058787240555138617430957726435018993641384272704739631990325487777381138944443738210694549848608829677243475072399679645927606005514286685510561264998787698458312516558296990601381416044688203430257022541216048001547111523895914957704658178066363431936128340367489485908353053190120423616965269833876600821864564125467997133029509795414158191930903706463721433, + "Beta": 2511384663159947171848577381456670030202069453112933690083763042503431725605911432818446128387213227909858685783808731861219158545948489157692010396483663460987480818975354599811633433858285157508799966744917089363596717682709416910020865152620832152886884430036855417184837492238782616280420716961956880645302042186585327514925602898838052031767471084682075885912773149691859240930398375056022925095549476440906269753897796392689996791670274860669925830819246295248510808095007483150757469522228312659182217945939448352526491281922919531767950737549445480923726434619431664450865813241399423202539189402601869878896, + "P": 84334730228853613493361154666043505556794946846607634722479260020138533156307306615043600707020900906641806097691888332882802687632517276018526948979447828548040557447380227811686589377196577107144563561888105663807570453806518808386387148985107566148578090365670664343712641831758266037345089816045766541191, + "Q": 73374371650177124955913648564295826914400543620938722781627109839160819998327635684199058950499412660302416092595828220093461853341269473386176481322610518000535738281366033308321479090725113148898075670859078705371538865064055168034045529984226177786748536728142461046588867058018727060870195984489381298273 + }, + { + "PaillierSK": { + "N": 24557717486235155387918555720309017052841277656823620909281437342057785785961160107269860481929131609243559303793968249300591857747317588295556342888898289642397105347765475078003697628323575952585323816216110067678339073098688287402086593245505608412307633186103670728036882513733369973768701236408917017881089409834864186883207691306158182222244930731834399937032206208208284279907588127904105406274802200505202815030026318360175262568441080017563800516935278078525151354115070130974112322137750543601605933088753053546219918084146299667524346839485148789457043281859983443135867651151383077706617584582443104054669, + "LambdaN": 12278858743117577693959277860154508526420638828411810454640718671028892892980580053634930240964565804621779651896984124650295928873658794147778171444449144821198552673882737539001848814161787976292661908108055033839169536549344143701043296622752804206153816593051835364018441256866684986884350618204458508940387559432963968431906293146711339490095333485564893735134945159238370949007228149836087691956958097521850840323973792800733759107567348816286236257985388212264788559100213927081605038580357049366316656813013441105039866074602126452858048379011029580737443067085389871409799155651107123459764048839395772147822, + "PhiN": 24557717486235155387918555720309017052841277656823620909281437342057785785961160107269860481929131609243559303793968249300591857747317588295556342888898289642397105347765475078003697628323575952585323816216110067678339073098688287402086593245505608412307633186103670728036882513733369973768701236408917017880775118865927936863812586293422678980190666971129787470269890318476741898014456299672175383913916195043701680647947585601467518215134697632572472515970776424529577118200427854163210077160714098732633313626026882210079732149204252905716096758022059161474886134170779742819598311302214246919528097678791544295644, + "P": 145441391060835264640387589255377428421205304994677028339684201644568732713036797069009889135329297017406559270378027750063787514419997145185319851778255116117431088852597642801636994634233821847853212703631394058960630111084342670398082741603619666756111840461146917428764470956361066094073913696544749621263, + "Q": 168849577875414754754717423480125813633058455709935438422631688086973649180095031162920133225556708444094575111700705008643956838886385239806008149186246537878143147062044634009265250342802623021119406759094777277179555823857704091410167339859469961226045307228056782887504868892807764693015573207106810137763 + }, + "NTildei": 19507046384150138572144834305268791872010813184844953408040850818518487551029594815520703930963345089526077240055304331134646011597187207322955075968845313870636807942623732000855179797825038395790910387546565984042199537774282663766074343997758446818093358577822893234454674422879336199643391795086490043865495070434116466060891039051414041253627623059893345095206211866816515255699202302718931902853467750752258454430632410586281595858823376331926594035622699106347975093181136328098490123269780879562526866904729317363462527556185067810958285187041389905719454118043345773949543771312742159211704694221728925050077, + "H1i": 8245833386230568310765713172257064449197259971857631689665327499611661778853739187560098450905136971808814010143193665846552224416876610335337495034996612242487546666073384898179629788970135118510318976592035918673931386035695182848707063722342178923819608100396252290108861177763594092536274835588284135371247026890515532140512416029724044103863436908249647477024338010407856594658517925180352098718209395852983800645012833634869298429110970034461507519938227765745609702820069628169428287747743008572216661930008062228046717142999560769620084648452008517128582066210040735923560162004324837284472283766086240096836, + "H2i": 6662518317359577123145717470150229332038308455150233152068417254358639567807229736126779922940079881166391224629537914180524071112284497690569981245757156236540684716758540464458691784520370056565556686406397362880645819346553206344733894429742236742916811462727333102681152513750071546047704597159501130452204736829145527548467053749585927820998481425676393437755248443448026727332021245980649779108892056267955275135835566967911615594500190375796478132494438004442502039336011987747012060209235136591931410708309914746175121094204290982506974740468487274805654853499909957969782387771409766696884453102351335131416, + "Alpha": 3533506718431649608188671693898277036043699465683693225480087098696912731493906328618955801095354985634451732465928421609329768105490857925455786200487495141329002288426666974212290776721020695970795635312255926948598959366289415555230667583163470639559899883880780599150172809900311914055478803741185834694585459738270292583948208508711543066527251438356356100937799450078265864644112516387019986773525417627971132799731720214110771757309478197922289037692633751354828866653701626682554547048084518003394985447198061101471927202867208296328090805306638501751851223683442847650465419060133203051430135203198450120768, + "Beta": 3837104910747413294698833671032775503465853241585556273308122197618318367284469349800057061785253387332430646059570331296283855348596021217218719947932314002898335688348247538341338261122007272048383987246067779833378264067441345343871385754147827273715309409861401351587879087995162613109810429088370486193844939398752732068584416788882953241863614176295252687383768896832163016014988645130482912536207488841807056924773285228518945933665128242631237761209365227461619406419258165443582296267668734954774393700391777339406794979021304064959686575214702852860203596397524802156271781677805262186555609843510555266954, + "P": 69351714499164352841133544376913406683568937707575625313819384890308903691019372982979258583722381885057274504707274006060020607382560101137652993277324409700126361862211800483805840387836470256355872553997550888278338523689734909828660125401263419271788066667096560789729014202857991374647135948147098408309, + "Q": 70319265086031820267672376218854030151853564517560046378002777739638903944036400782192162385417057449570575912423159687263756087880810907761489988125136593947829990759802275190042270643210369254073545966815530720194025155945643476151199919757075325138557473043313997205666013125376229608881026542929902507691 + }, + { + "PaillierSK": { + "N": 25426930280784666607606746972226629816390836406101760757894333828851029177396313132730655355064438268913444990224300279043966882115390306871005750107089676177274291829703478768049119475469904646186102630523735407099380813635740298491615138566299239278552219991044636370637787272057476688597457158870793249725037539036971801038135589005018366548535530853431434127821016870504508369974942516063592405316224221191332656007197326930945916544615422255745808992711196161472306662077695091105686782643550031780976452076394298687738804239860402082572012384756023741770579037265753540291200330489663425305591300581375810889737, + "LambdaN": 12713465140392333303803373486113314908195418203050880378947166914425514588698156566365327677532219134456722495112150139521983441057695153435502875053544838088637145914851739384024559737734952323093051315261867703549690406817870149245807569283149619639276109995522318185318893636028738344298728579435396624862358699664207418825910673720038067370128907136897186808700304312815355391143066534039055753422546920363539701047072081735274771209590744927853739632558406369687028880092709197250898665019270956959199921471257375060482532259385013951988098571993393349328980290825656961781826803719569685128445102588733264699018, + "PhiN": 25426930280784666607606746972226629816390836406101760757894333828851029177396313132730655355064438268913444990224300279043966882115390306871005750107089676177274291829703478768049119475469904646186102630523735407099380813635740298491615138566299239278552219991044636370637787272057476688597457158870793249724717399328414837651821347440076134740257814273794373617400608625630710782286133068078111506845093840727079402094144163470549542419181489855707479265116812739374057760185418394501797330038541913918399842942514750120965064518770027903976197143986786698657960581651313923563653607439139370256890205177466529398036, + "P": 174049409634418354728989301230756060276531813012877023660492793492856713949605599917193523146583669237192250415004663431948255146006684921688828313322967746108117285321157243162134592062382929353931479716404613268966050552365890035696827184392548381973972386281929880693043955442634264431528914478625353996759, + "Q": 146090298922545031585252263711475748001184766624183486759915451380940873739203848068287375324546711227061003498048500028448118979427247478349501414271415675990131616571119453441754860542625188508645129417474935297807689168724484142898988056376688661138646069332509736034502767607889790617172180925283927494943 + }, + "NTildei": 23152014987538474443981864957450108360368730222338387023197073703199433440976433721119932903702585830061889122997459572972844690769606360092797288933678706919780295524924157162098155600311393002473400910209963957356658059465625550013802028155727169700363447484560076118528119099603805871704907367936874708603097207723538730323658954300059639796399993396158312562344774347736583887241300539305022841528960825498173969262972643305310436646936922371473924843680433725492298106025160233518946682683995639530240682830216962414106728206472571391642863298532238187029385717385465486442670483492426780279028663755615213532793, + "H1i": 12363181421750072444452153498420993042576313350037116231651938624846418457551775473694639822398397811221519652689258641333280674215588840846801469149632637218166688298253175575815182529531923482194324995689573345176005159257060030140319762327721966645143072608315996530671724937422540158356040074069638899922076359012825782101241180054364029727481655087257189608857542628641382809743032244718810940236638105511593847511051666370951737566608803717062531712005761529393714976399608669227200920047496214547780535437049226346205234693138311076346155734041039255674281299179038758208010543919499255385180886777129494825482, + "H2i": 8682777201880324750518880727430336151575367311435059130868401069786606191837069210930238395786890242441042756933902325200722137532506842865439955002484930147247464305393128404164694537204425053815133102240036413219596432444621979926808478187380367130893128011362404450857820191934309874033538310038990970985102726202044297848439902949335090195087602893698372352019958041157912394342835348595189579600221136303879849640754489018914367774213098699094740589628299123379137333140334430563949867848205621548420939610736803355195666596447593023070453540496018637875123215912974590387664296404372760401480720031102436368406, + "Alpha": 4617978587674074448758226349434055245923046066767171865178528139557546473817889209471656442462551094919753982741044290469871444517380567587566923916405220517342137142164526582679036163875224519276649333686147089871775715705191811559064961881213137860577498599883550218659277625000047467838042413499188446039865824980436318014326568176132808728689865409832241745053517606831702160554334678019872824220922058016767823697286134042944313638667138452740824325553768735101023056491622045095767553760502024523604303088647684153128453518708612323801962178931147631761636141469209480555039362810248940530132880027138623051601, + "Beta": 1974600449454523560217349379232633340390044204213583766883468292980171263796073285185353966474199781451579426492710038603802852044866764357997300283120584177453623259502403305007963185868629294081285601130973097409195341794190324638049193079999781068762780309178041846968544346962414953396060315472083470477141587366684821990241669186133991772367981222882553414922668768724971497835510633327414762939215782335421855154146779461456630980815093580458602066325439917791778683099351068704002866949315866694238303563138827368674085431734323457239410303091072753553791722553137994922740824542340707450682924903472035944646, + "P": 84998605105480468900854274823253497096378152499620489718142831733832177400127384640158469225018989532246065016249097776827855436286983661496989681649995064485435360849949014203289316691525792449032259221827750396224407760863859683749326627775354621925849690457197225216892381907999646112515287951560020144173, + "Q": 68095279207251655839292529783557689683149923676255038910226897167733968998378999348102723331239392081457152347506770329592496506282877390437906499017149594678944043319420271013595706508888982644910132395728185124837296357162395690549467477569680425599451962259216349232483137777191017225523587314199259209309 + }, + { + "PaillierSK": { + "N": 21826998854458124219307940802461092566951186290501986871650637565426678870342195100975110929977196354239818176281702600243341119173726793397927776155413865970472030310496264853269101822390048334307025847078881477311574718327503293039593648518380865917661882932682736746056891427414821177732728302843830931095566318005380698573999655463978829154404173935275682305924709094236831344765140105126286927757346487413956467233229980431744660378916598801008582620632473192668588207632316596877500360405616745563224274371794331892662293014614785786411678774163017661699026323204388760203762843584620611929012968530214981107601, + "LambdaN": 10913499427229062109653970401230546283475593145250993435825318782713339435171097550487555464988598177119909088140851300121670559586863396698963888077706932985236015155248132426634550911195024167153512923539440738655787359163751646519796824259190432958830941466341368373028445713707410588866364151421915465547635139023705847036917535076759396950046845551245429382693188240375667461194305779969898533995364980061623377369346414385408792277424828483170135593420338756615073482523746492659099218989110831660459444349169140684158086445290447077594046984067221881095613922260679420151735662801179797538187630782996979907826, + "PhiN": 21826998854458124219307940802461092566951186290501986871650637565426678870342195100975110929977196354239818176281702600243341119173726793397927776155413865970472030310496264853269101822390048334307025847078881477311574718327503293039593648518380865917661882932682736746056891427414821177732728302843830931095270278047411694073835070153518793900093691102490858765386376480751334922388611559939797067990729960123246754738692828770817584554849656966340271186840677513230146965047492985318198437978221663320918888698338281368316172890580894155188093968134443762191227844521358840303471325602359595076375261565993959815652, + "P": 138914193784182425593156267499844024139491827112630413838932235546243011154590202065651746820024119185955856631785685368711258427529102733054772290695075776121614643359798262010876294783350552235473171381399161517111171804433552402843120928671520647522051767642835202695433256439261624451512467794099828124007, + "Q": 157125764184822074571429042960191230170991005672193126699400377939253411221938343120838112946592408104753855862751466292215817396537839101613539143096719903316826599225025349548425627644044530006832214292056889007234948319600339228380463877357053251985746711040194717204858261542999392401125239170121193167943 + }, + "NTildei": 24624801721616956273567956113327958160928807465723596432119479470729171575111646409463568823398051088156549831883967282061671258322996299587199085144384091339897578879264641087373178695707206825602430401156798050364091315150315071672757734095648723441991192452086888477851598942159299209451520558025003619778895631289413553080382407758681872227964422182664481944612703248369845187770258266672690120847655388939930013275933674611834394219417857008342789889476961087750565268987948640076960687145824943420810790811337586248756086499885172169482429184987170544408759197331260068602069651267859331420520029825709978620069, + "H1i": 10729167743901179254947397571313802243248464708814716611834731283062164939419148295193303894466168597283053060586527411331887229950827846180721205988014559599227726488224920399348244941717863349348013076471469008647322478863955890972927666362270829813751967049411057825534018570006950710855639456096537606662538815032653959156955579876113647296248382769434092539329502397505030667693596986208297980350804245291434581153349684336317936833899727476094471199373696306532809047016619134461715693054793867896930794394959253695634618690572820012636945666692937658076478781384854552733418183634491051818033600756607712899933, + "H2i": 14051950471688030264555239038870418821637198585986798721972477949038416709097590484633248104408953905590368876143703728479897341610187276791695545329103963773218679654058555603055350158277255988946312538634293250440297039322109083410661730737920539584913022793678289465433083044324763016386228834389922616917177548121082858862377522424299473290205604975617039395351106270365748539246993156136307219138123292314488748826439419017263340269114026491297035603910078196711807411867099421735700100927832019196199004939694348565943540513783376766826365833338996113985660951898372535607712429624956691170089978508252810182740, + "Alpha": 5404221740721105912513750963186095166323789940919583131231308037059241781825968224159499453867965111118839577975441045067969490122323753119448630177680615468610457774746237626267039660599502344897831941033171086349832385369661434225015299868226007922134291291567685013639571484611864685845173829969825884778866921338715179779052461835336519490747331162725403760923201966927568001130007253452799293921738985284392084621398780151976557998660502449249226725624926154779719610271984085244961479744928231496563837755048178615413905210148989510938131861630402488086277230839157501171368709090317084572694926881626302269696, + "Beta": 3762591094256339699224516198392542173593698491874443519946956982811008467717440207540429621017602743636146123227737672149181030406176970766703235501416227273058287873995624528596449648877236575799971771707516940377656645539659352288953240809409250814460846892947516495485334911873893588253591976131723546963845783144890194694949624209789897688827361928752092002501491290940323779011366753783773075972021051740235975654527429911279174450069923413186430494357504463109526158591234928712058046654935348763771751117588405664231221514799794810665253795512005366778292551662307677018759004997790858122139063962007463065095, + "P": 78627801181523514524115724007926674247851834115005510552808399059821004030674798309904221774345580007205031695223713872497098240252680964852846773699458429007856315621643198882848556651962266582888838679794045065925147268003374531490436313384179786774903226631803394365859890188115488811962284557651647329353, + "Q": 78295467225285502850962974358761057727193422152228839851794623322143732150901579695614193647524356502761045283965640476822051841598305320753053372576908071451831934481882217503860914526768658745704028269070470733723000975445396053208708134132797535363161526311350042573774319868613719058258453817678554644083 + }, + { + "PaillierSK": { + "N": 28965585056747297116093911172736688255709713426956305422466158531528275312753459150153960921956267436982364144826582132223820734033324766201493543258608792234445627909807277287997711423289139722234578296129807071533874463987488056628898906605851893580941513478857922136052768080724011187616251985096791772474528536681272356847547464018608369402937013137384941941679980717947447028786538113816163188766781601632458285110278536324290843834804234907596486813566889336127831055234537556688899837584494639533114269903480724548402705250279508044957330023814730263911766908270895088220157061700559020711456353099241852954657, + "LambdaN": 14482792528373648558046955586368344127854856713478152711233079265764137656376729575076980460978133718491182072413291066111910367016662383100746771629304396117222813954903638643998855711644569861117289148064903535766937231993744028314449453302925946790470756739428961068026384040362005593808125992548395886237093900456696874444861099344780441777149225722858140866568583583768869565007143692685472702842061894418250218457714473113388753624767751880003844864512727138552672844626853825815577526221734843773407250647839341735405718527195533304583667904197221771484184574081093155982852680701638937209482188130445453476258, + "PhiN": 28965585056747297116093911172736688255709713426956305422466158531528275312753459150153960921956267436982364144826582132223820734033324766201493543258608792234445627909807277287997711423289139722234578296129807071533874463987488056628898906605851893580941513478857922136052768080724011187616251985096791772474187800913393748889722198689560883554298451445716281733137167167537739130014287385370945405684123788836500436915428946226777507249535503760007689729025454277105345689253707651631155052443469687546814501295678683470811437054391066609167335808394443542968369148162186311965705361403277874418964376260890906952516, + "P": 178089983473035302674000246538915761766862058882219328198980273153295806644057016290322416080547763839839679075048359015615216203205988656031953111061239654369818341983457655397240622331675270529600175121859916064323060154489763450792159539065687964223092159501524386227134560508803732837087296212506906197199, + "Q": 162645784405572655151265082508570086871699632786440880343833277256412092128193712154895367002110048956118169119801231081898120382062742491556843973480195404652667023997372249660504162809349681456699593485942125013268208041398677984997834676354598756720305600607184390027317139788477413455404680625844039804943 + }, + "NTildei": 24270264760991222657004405633648149979966387612679246634313975223901670711222461444764696178608339331683451105679110737969601535450571798935560415619842438587929618815204459147107864745619438033231353766146096944880632292227040943339429027144922020627152980690541715173185237669304603623388554654697778423258316635313003552560010984673158685283515024828040808281916724359553300353018350848157184280996219984580209773532154969840521421777484077721779465814542849137666216784574417422824936129832031753847371233634301199540388446906147801268808159045744278030696674050941363127582768125709841444653037047482415214379113, + "H1i": 18924652071545194723929052848984512295274019982938722070563008732609366280836333239210784808523125805851433543943555917452070194489074063138181950406806450239876599884303334375984390509936958856508526113118829727088694608138335214999862416365718863020984194886055654025518126981247103812034386816028741382896899250151804912996527753697124149386162473324380727667008121775905235070581891898381434382389353872136993290068154429780886528808028393281178910750610630834614174168891687760790470820770493387298578226183690937957084757622794494597067055242931313950546217090438442846116324563184959096088943547680495838735105, + "H2i": 11894603274887612437749865875901576435891785160504373179161089854225648115414634386611750471331832195938443416923919138217464099139104903233983440460909735816320393310179213624272613414185593602916696630080192799123079142256502335101334140234753590068159460244121462188226522471840465867531477936144527491170226817230219007339634423409724853041690376415265293854098365600282132603310487505111292837244757446147686758990709918353806796319833267683102971707925680089954601184659593729705592112012344383896194374334896432473434922688390913127061987689388656127567822811454578679798507104896923641631902477380066527789274, + "Alpha": 11083001642443217173084093461781951872088182795514707663004408480389822784187218553143886562523907212067087079873553393626338859611220207985278931285329018975932354176288178105053330579707298113179867045575255848220853460354625869605117053923382736559930921295544448349093733462889759493839982576018820711378613439466557625725643086345380035249115215157951891554232000312396930342220550486066773211435739344662303481433336774708543067586945168031086005686057770052117127537530924069856036184262689503994987465332635087624623014382013275842759948037696870886524096716435157646126499038721665569931857777769258228428557, + "Beta": 3859845581311671438195847545641589707370159096982320246346301756030977033141725331248357490866055086630951913636422140759745072187755062155066895059995026509113507695976824677466897180315460141068083431947899428512135321268959453001082414575568451411115221008586534141362709864776391658464432253515900745180943699779102818954194766331439378045520742655333012570830442963566818339899920504289009741333227892074221149402593350368252110290710430353946025817717251840240242156010579011107664096940406800962645669112635284961354536176930649041875012615941598728875406393232699403995916676975040576796711582235353837302782, + "P": 83536423375160133944604276400320250049537944012819589339473016716678113154370173746424448175642921267490956105068039727912047300549643034049912618006274621874834827634185043384766287175213264289003635136193008988742707313099015788966091482798775248698448698500134881577243790883609006801832598718711079282343, + "Q": 72633779914163993624079760496234418186572719972715688420151890654951622201643212647648597949959407536005953720558733385672395062068762798365314735236308595878674280158065425597867435319208945366320733541632387483365747726897341981233502055227314557687165813309613006969845090100170327540213282569892211993699 + }, + { + "PaillierSK": { + "N": 23066293973374406352186341549710577101931792038463326784951672047965044525986774722162218980646526846173276623552222908053887965034734280403404982654764465774142924999612044923519246991537522795339027475867537898352604419105038419596508715903602845214057186360539596583176913558618828990968259912597336382898159585195755714227359627789839232610937086396093093556496714534770691004138903739766654412529572767594649642255510057768084840434426483312601705368376545179699092000171333729704072913188427505485895219155373681969348805237229715420070812172940849661447352091157959526687060051382662483193714686499410808753061, + "LambdaN": 11533146986687203176093170774855288550965896019231663392475836023982522262993387361081109490323263423086638311776111454026943982517367140201702491327382232887071462499806022461759623495768761397669513737933768949176302209552519209798254357951801422607028593180269798291588456779309414495484129956298668191448927587825682074905554022905318347346606018706471426610004597284162329484425396505536668791588666036605025109579653475289448891122062926733987192543727528589365451242341389609952122484603387586065908922318424777282614986538609466869215863767373391601546439196486444061539503329780885589671487164724257578811126, + "PhiN": 23066293973374406352186341549710577101931792038463326784951672047965044525986774722162218980646526846173276623552222908053887965034734280403404982654764465774142924999612044923519246991537522795339027475867537898352604419105038419596508715903602845214057186360539596583176913558618828990968259912597336382897855175651364149811108045810636694693212037412942853220009194568324658968850793011073337583177332073210050219159306950578897782244125853467974385087455057178730902484682779219904244969206775172131817844636849554565229973077218933738431727534746783203092878392972888123079006659561771179342974329448515157622252, + "P": 142204836906214060873846384470979916386483113860696396252612307537264463890091367408851574309071041389934896279633370809626009464905908939267600120051485231739655219188728461713264233620303847212548754272904819687180198121685971720895292202017684896803764141675933068438191432264096052332501921978029012644247, + "Q": 162204707485350355377735594731558001338565869289543940234907658908767571398019361284465255043169652994664526816569736379561048725394720905359720160870002769228534296299826048086563710361348486141528620245619307716938634038324809960743792436176381561550709556509138335169861959556795251518238435072866638486563 + }, + "NTildei": 22506576461085135780362573907053320593408898740606555705125761820734358361453740627473014989120838109574225118084323553343935368507454426684669302206023491673369708182696668019047033262452958436979773813858569395579184556693209984272241086731432400243654026808594024510846724764960489943999117152230403301094930602498252655238753126387633917184116586137639795301603894771525260979076368776316467282412954856805108559047861888345199253349522959422284328133076963926951355456349950797115664974267315451245791810244521488270704808323753089871618817664022829503509291733237497696682114050100407955680454191739465981685693, + "H1i": 6260452569900944861986069131539031932247928540862459626102490631401083814817021939458766230668711472030785965580037879111866340334831309102372548973224351047909263111161588486381672131330100163202665410912852514688149016670996784755111783847086590967866825685876924922692805301002025966569165482864963446903248975382293185298064425202352462895449058650399368234037685789282935730556160720673767432268680078795060520708801163461157592847975799979388026587989697791575773394091946844865143014222257912222960607124020430401385794699560783770448674739707841753094903263054094978690449853738667662608369754317637529877915, + "H2i": 5428367735697510414461777653356006304171002233241323949274783449807325590487616826669713724641244491237749761268118469192904653339552712704003752021300781051851250719602110988020679613046369316736637185174238406299174246052458021700656142467547012085226659058981532124861021046992536880144511978649009016032504307018892231153517765257055932417708662961799065890986365354893822496747288201610070639657723606138845317266321999857712591696598879932681708523361152103385596035928252695126581405009055712536486310059750345626118505675687697540594505778929052868868586478452623705695931386784811468407104756040429603650580, + "Alpha": 9967545586282281564226318710995034008863600084119020077752295545841370217469563411923581063909253581150665826566515794175447025827976296668393845988937597960704759949828233541641044444785261812733022705401670944210559903591234738402705765669566371852585928263912774134857830599636942775701453057911517597738981999435553365233824507966201241278479330893329886817259907411644673251459788461838235058170804521409726645199890341858033632684159057495311973081437839898633586507566045476570700914112409383650753625952333610092481478108857473796851927157154424862678217172597713157128031451814457997071776446128240910030646, + "Beta": 2851897375151777887287799692057159791872897005101288168206880144593456921455592765126500082330530100605317028022178924853038228744762568580551440427037037452286276937035519576052388976388807326658708501473736603178067105670894014905092826262557835731948743111371237147544087437718668031055244802562686276027898439503366867316637014570417307392171091763428253141075588667493271693082411464209891131203973914168912239214932039765651259330358163945601979683592374995701614819184222546916789362915816489276546263931998056945069523040375717889568505019020838186990032151991810029362928731369040496899089507968639022163635, + "P": 74401677442328450333825224989924404588771811337948973919111427142771731702080756949264560971220845828676048083628043971596460231552160748969281800564258760342221365987791868660060002049072411396599695765768131713759938903603382185350716281025477057635310288278099084622984199940837415254896298985445916450329, + "Q": 75625231966479630334429781175990664737352348648745588949484949157310941932346583306687895018681953581144134790622876803868105034588097494867586812661544509629460071813148118329945135448830960294752970752825001607482802216673736764975124746902091656398523891595428191489627017131406009038061743288075377089063 + }, + { + "PaillierSK": { + "N": 22989445036956416909511930861631096675290248980599136583415288658679229692109068809726113559689055380738613859233578946124108469105117381480516877745403859500659002541762180469171815768851880373216330931435441870919546986281620194577420665233873062685520988745670714147924823808673608737348094533381243381638074538770793147019783692509591312857413359951931924621418619953751821857825928220866955523100166192951451532763455151700765056451090010712280093049300172007024798517755303887961030176813282043751654407213313000221448232474846476019957708845960066021334895815046628707259895545301970949083299715515283754620297, + "LambdaN": 11494722518478208454755965430815548337645124490299568291707644329339614846054534404863056779844527690369306929616789473062054234552558690740258438872701929750329501270881090234585907884425940186608165465717720935459773493140810097288710332616936531342760494372835357073962411904336804368674047266690621690818884676659416482719702521453470598007471097759072789601756921456482920896272357734781981161586742471902645614271666999754301287257166038198612981831537493114191220931596960177626268204650050544488489379628653813894186787186699518731958088864645135715220462431115446344483531025522064105154153724098136138132938, + "PhiN": 22989445036956416909511930861631096675290248980599136583415288658679229692109068809726113559689055380738613859233578946124108469105117381480516877745403859500659002541762180469171815768851880373216330931435441870919546986281620194577420665233873062685520988745670714147924823808673608737348094533381243381637769353318832965439405042906941196014942195518145579203513842912965841792544715469563962323173484943805291228543333999508602574514332076397225963663074986228382441863193920355252536409300101088976978759257307627788373574373399037463916177729290271430440924862230892688967062051044128210308307448196272276265876, + "P": 169771054917407652962226785802749500087428460061196252562390242724494406164659032532137268081578587064177740400630697028859412105258742820176871107412103813455640938388361263814771098606761817135307957105317642215837535726246229904774779543754071776933374749427860484834662728181775123641887251287683676674543, + "Q": 135414397042773927416422816847367342383735973725149165342386798061485659116553718770855931845102662081982563819490455163303069831499191494877258278813081965186715716173022268893722668906419137639367690850687730217237122375201208651266751572915722813960596203387875533458170766076067615133105016031327801679879 + }, + "NTildei": 23908959017056763196840100500671300836099792532786399124182388698783878770422903608118315683994247982561837480742639859126912515625980214150624952310740847821394244765940541487310957790722980060608223708236470994666396784469869130897343345578511927471667957281149608903334590846942458270028093567484863983427620025195519535151885333977737970180831319913278581177803484312530861749246769316991953742029493249408994893815852931548788596710792784211555741928349408859360556147206033843299703107651460682301339873758006292633259227809164753504123907130131438293879935585068951261376990332037082026934198133279193271793549, + "H1i": 17882467143952385882040966894148518186108717498696685249815342728950677238846292891592182218042833281143558428260868386097642649171580733696537150344149856045308326728288293990433695036194770575200134942949358426796354385901649518067341048738928594056227751837467337080971667754708008761271700916390444070536938903652317329971785703659006271308298565006646007697250242556555941225297551634220583237437371442514257394811924782273207792238045411785301670001851325640850333724170331734997095936868890832249053012592776972581119421521090201792821786056522812901878263191943579206745712351326475311952391849857177559621297, + "H2i": 18737915933081860710066371006297062560628480807792777063893418598193828197060179177464227877833024392823615719570756743703392941056112536386517766456212365200351744624622518102897120178332649478130918599095825223956914879778709172722493105274188101758331612604513750431399276505862384423310643522880710158991380907652635704823552898217362281134172191556496688999197505450226667137467853554707860446517571235589124954625369340480168408629446687492900423895984715662373754485729441575723180367057056932006417020044761729096965446959894778576251216599445306737184728496777595968143501704089802309590961040116437619461311, + "Alpha": 8029010711264237208686583647164811968158109425659057631367860306210590890623119432415309662798781640482188678544838817593269712185079492722602426167492240877156018254541244728892281478095724002607411195562643239235702432408238886235077843881558249797787905723697276062970696603107577285204669526077361752040315577604357447557396742024852082524293208840334254799208440835529109326493783512371414919105746155679996258796523494294334915910787424795481466007638424760616915431846787352565926043440925118991103886150898509271429364073081146888850567665761313763116256069151072709338326658884353916402124663190551121873893, + "Beta": 5266530113852230550084288506942357778691967251762600372851114571694954288918262560413567134536133792689461450400759089249736806618812717224780213186826561365227548041636574934133158867728469027778313540696533575604791658277274504345054810492517983709352326454718436618455579063089157985925626903716090918233597060085548447293449899098634144008717083049265699959852834427003951671001941225454538680440660992539657595228946260067521752321228638737183558034532870820008313632780811853816629669187702528306371245172088324005252163831614572748692639409538824885646374636346968627341895205671671913259344867806280528775399, + "P": 68232747950411669962652970993155860905862700905775823133260425975438499193246191553833963912586779485845595811234597863233489749796005799142950619180075163950938951690156432894105784198836346071525655672442792154362260783757029572967879826660051745556820890073203830408755437609502433804490969668332313132913, + "Q": 87600747937165971967546408684812829899799440910015873925541451924721655618696199203729901207420601045307411009917597339120480990510035294907558138516720743300540353168168320411523941481172016365543477632760665628341857807274943508542779881242975342056086928731802566123136786446510713191460150204007187907943 + }, + { + "PaillierSK": { + "N": 26765820551543897350163804684120203611767570827895919930248883774681078604093003345641475424749118937599237260909231273866120939177939212397586016268750790898637592226463752934694737447301816514945227536805037447608828531724637996388653504310207845746832173254695954514765072728311968373508687925080640533054426412296335272757447560041611479373492872516543101110152781041278827083170506661741675786596829710705108091026741065542289487396917245853829391302151305432039427361327415332284967992658183426259780273089900413478849362255510816019715686834751869560208565218599855638253832741610597215051301526080396429673097, + "LambdaN": 13382910275771948675081902342060101805883785413947959965124441887340539302046501672820737712374559468799618630454615636933060469588969606198793008134375395449318796113231876467347368723650908257472613768402518723804414265862318998194326752155103922873416086627347977257382536364155984186754343962540320266527049448824613845252708950825822164413003248484741909505257794559199424792717575964507384811026910214360894511945852411785069577347217126262165352387381730937278966516422237910791112520584267244187977450916267888649540090605380683126275762889855110387401131865233643659771731021881930008091480412322081652964738, + "PhiN": 26765820551543897350163804684120203611767570827895919930248883774681078604093003345641475424749118937599237260909231273866120939177939212397586016268750790898637592226463752934694737447301816514945227536805037447608828531724637996388653504310207845746832173254695954514765072728311968373508687925080640533054098897649227690505417901651644328826006496969483819010515589118398849585435151929014769622053820428721789023891704823570139154694434252524330704774763461874557933032844475821582225041168534488375954901832535777299080181210761366252551525779710220774802263730467287319543462043763860016182960824644163305929476, + "P": 170873535042858644672015112367556845333308351782962674316538868671418403393696053449264165680645895942307218412402552134799276491754103316969618760732878190458609230532121214715984216886563174667909416408744874652622452067179821994989047509221114036328438271455784773366073120776653463549689768989650030081379, + "Q": 156641112064723607357643277599593702153067195276319425320653054208559094341658679277641998862363386041011848722633689837351056210728890012529067766654965367022885097950818295986758734603085763215915954848619761527146728977569627772175113545820534749077863216676783545344297577070083735318650932446583093662243 + }, + "NTildei": 21535216757910549407680652104991801807551277821055084749898261180018921057967636682937326967001885974266934445470164566163553732402426485068937055885157884708107831915860874810680005899953177564575487854629351264636545200880690757235397759323301186544038781945176364835920119391443419946383219333711036557841708247979735078519195169482823973602757945096038817263412702253599235896703447603256619691872118562528302191558980543606822832121806758077560038707687782823024946740773579460460970576836576510270117024661584885237990761267145728081970596952824870186296634532161287048494225568514145454260485164417722017896793, + "H1i": 21340670561523059716714679892057139696102081845076411742073308478175512019057433841906888676512301543029344769157325902912093412672002250609151728967525088397879718766102464264091937292773697463541295569254282682081929334091552681140741079505800568846622234936404631021987134008946473208217239006561232141879403697493568945888342789443194432051100416301453164271313844958548955710107446304392223480341642354859909726436657460664886990094300717377570533702592026898325230973796505117448509565771136433009258355312880363938146554183496817226713643772837984969509153987532816083365756360269771784543463473764060944243393, + "H2i": 13164575966821088263438901897537863320373518394966208936536975677566631223422075091538717744160572133441962088697760963870642029503024131395481232921526592944247151993724594158642555504783346759879810897248479733393877069225462348057220808768721910601698156669005707643224776101332680989835909583347649126824215664135071363956333682309690096980558956164986302308517018668980433767920307853242317477059440702714110835588983808755685957568010756232365179714587507580062180436884413071234372470386180255662004757448151472324051790202063990275025279749843645233943896454678645606121324427758216792679968642250833837022451, + "Alpha": 4741122901135866343734035968261216533299139889310150743871178050618780016917991471029870599460325444451446366931347528269438181424672009403988021341149559058405964789174777944940347112467997878214445395958730711319677224087362722715601309944515885072678648568319953026859727025013755163400799943598302587797619521045428373821998818732336930435792003924457909818840492236050283481389629761678736694885154581881963340113982275964712927927823892023585845582923335244452249647203449801881083688371128194342032163649397094160369179716214006246906476490222544885722116723296448924937151632197086065323338866794652638262125, + "Beta": 4377569432115155803632373136702557600511335610724444737091619667151201799095868112516268189439997769361935720666061035567375096193579210291775065869907741840129458296507779045487185094340388180900721578622294332334818429104692182226234836060148685434933536361744671874942441606467052199097948571591796877320386173357256853058743293752500680126122951723713406614386042089262190793056951119546676199145659647794684168355616755316128876117520636496321032211026580793619694728671215882476608943513208995020073331403901398034589854011687841386189919106692634020573295188612111825490367626856384226335741525953032051282385, + "P": 74792168777388935395178730013196691446668052746571217774468154413461973944068373290364788107151959411677218343222264053928929503055372129795458704316411680520743710203524086512404459207465134029657625306915671374948696444813431196721518303300600096809172638012662871217393817606582350210933892633261852533033, + "Q": 71983528188652573988157425749774730762044474753710674797659187146638747279500156667711865807131823998137283049460265398045345109086649250173426754634760087433898030993624550541338601570102023448417819920414529434229987267397129470908794034071477479756666896618245977858369558869334273714313977016742355766289 + }, + { + "PaillierSK": { + "N": 25178264119956391501302431185322476925566669775715319149088407359886940712517801902870915488681891496938667797663046408577082098920267076618528251776509720113409584497412945883175671272725293038698239248980784084431763030186390276676851313274068674432083515777338731141832224684969656435651219991361946938463702999499495989179181818153913120069181198986029890222004128052789345911880962469521185617435442014656230908752245657169216504019102335403027700032222188974060582731802289369613785156464307447861407510598881649065360032120123341622650192902300882521607632499071726985622566202695236328361204282620327759629449, + "LambdaN": 12589132059978195750651215592661238462783334887857659574544203679943470356258900951435457744340945748469333898831523204288541049460133538309264125888254860056704792248706472941587835636362646519349119624490392042215881515093195138338425656637034337216041757888669365570916112342484828217825609995680973469231691745833211228102640718140292067226272011763558951440785031476331402074439026993310236047622933453567764562025615230632234776315124465840549336047735241699694087072787414954708494603780695696685319069830147627533742792799442507698487599863343818273164580506787141198938089782305382047189324175659997284779018, + "PhiN": 25178264119956391501302431185322476925566669775715319149088407359886940712517801902870915488681891496938667797663046408577082098920267076618528251776509720113409584497412945883175671272725293038698239248980784084431763030186390276676851313274068674432083515777338731141832224684969656435651219991361946938463383491666422456205281436280584134452544023527117902881570062952662804148878053986620472095245866907135529124051230461264469552630248931681098672095470483399388174145574829909416989207561391393370638139660295255067485585598885015396975199726687636546329161013574282397876179564610764094378648351319994569558036, + "P": 141232314854412951288741344440600598525867224473849957427494572063208086011758485559099733430076118724049208078369916754814067783739274617532881138703203529253949082728635792338579634400809782732161731326092289322710433308712417287373286830918670535945520837917695914946493920340485421957473826159909142801687, + "Q": 178275518219120022611640528888385018111308234438137383006570528063333676991149997341613788759498988796652576622645279149932883605114129104396146798048502045418459503498823667858216314502106271758607639612494104675164013212525908938301706344694575439332950647579748672799892717743986812025082105140424047269727 + }, + "NTildei": 22093877887323493169549748559393057909033791772543279348241688481556188488900890632829245355662042125251830367334809071172991693975369819747538802621003015252984345165493375005789675251854355419905641691081015932728893097825774177944288712149754606255347843824540425332322900421600658104268269791653410976478688673647065241438635595439820650391799674980152485056735062546960385902393954358363241397528585796163701180117486993962035242477759328926996675358152193322589480968177026602230816691330731185765282004364344378690926143070762288023595848898093804741451072709811521815729714120215612110188603117979997118482217, + "H1i": 10787212679941641809601191414313539823473329088857891022556713155885619125517808738288420776581228517199035138832894669919005605699256105922280646348171609707303717972548129019434115967888798670636803018742891021411182569391514530236168484037498260723066697515932118576624090666695889326914935975396729037761447145248690281131645065206104282779862820515835614876750793124068211592242446551011681706039386651673871127127695674498186329425472900666551366610319138331310671989387721019032536479640900365762430296058557059661157482915202334500084411227035740307295053511420284168027002770608948849568515408002695013484785, + "H2i": 12983456646497293048459386805988751371784093548480732062266527998415459154204902153349102884422492355950552147546027468676863679687451804982680623369310284548962742153647076797082075935607196021176948631285809170968109630129996138580085372395180455835113870919792148326844590754021986294211120318271095745154687512045967806106775314826171341743426756014473124971105020911210317569477585435954177869307472975155515320552462260848314341223845094413975357890642173840339941554869652265214427336315821822368684394831282890596118476432629501143683404589556051014294172470677415700515137500472994765285289632922505068595110, + "Alpha": 16348444390648022260576861173231479265125222428400039551367444094603385630036305519925577659461919281670876752456758856295387743399143513780101257132299227715795651740969138108206684914007049753773804387271515461903223715362047221124749205687457652472449645592636044853262648933883649664918358548015514074390338778848386201089156989526218967918600016449283601785726189976061094639643966297129686239948509084627659989235036357389931045756497656613484937633297277631799945745368376113194965614490147946321788669727307583923306834089739162949772474066938583070038744781343325810767575214387802012949848027522011584524584, + "Beta": 2872351192394396685009108828172134869658140473111538075567365532625685759709958612064732895046807276292022698445408564619544930043253117566983721779118027242501141650538020180132000410980210710808215482442561861333462777174029633755154580069312654396795284260138614609500620405836174364373757616834630322286880027189283448217316405634865004219852809578498658328368710436274760876694570279266493403562413431665141843821413600670725841347255046089784701276167042856626873678103865457759149049977088342993511813722221288897527430862794865188520720431674803818009985345356149045289278004453952157021317355093743983049972, + "P": 69474716566946986964924139924417238116031979870041444027757813909331955272292840500155713585445071289925928058281494020145580020598412529062145849726012319042042948277041979467765911102387157082116604029323513409777698083063297961633765870727243404241090725327756863710028458992257893756914826243891404962561, + "Q": 79503303428497857549247896356302566759492812579480594738340788126814754600912605706180515286898005890948971623177984045958144558749327760100352543309574382772943169515084842958429076969938396454388523040789612036915287036500820123865905116323836004697891579472041653173624994744713096938163533558742398666289 + }, + { + "PaillierSK": { + "N": 23242194730800649656775200775540233202675597323866807821706313015980817450049689426193336450806274780026072878835451600458393952610349663564208170979818834827262822849655743287789154279342187750060682752334039354263591137720448845069358154202631407620757714837065929559179966203904720976823170650636059524399487135023699742828188067812609881790872981276464173035759661249804017496513624359705026039406647066008441300178105916662499940466664812327662278750032108436832069341259004799143733233769086279020862317902253734961394631758425136826181873168564179946601945174693635691331861638363238193163336605995426029296209, + "LambdaN": 11621097365400324828387600387770116601337798661933403910853156507990408725024844713096668225403137390013036439417725800229196976305174831782104085489909417413631411424827871643894577139671093875030341376167019677131795568860224422534679077101315703810378857418532964779589983101952360488411585325318029762199590885894644836060833715414622258462706817432831232585965890146122582040939199695235793185648746653119640676906156162984365374328867849324998076469099333686480619491958071127396703798142500350403478167864704569445806514718550177186286801569435905992599794756141294917389135650522614192718916848672778922980402, + "PhiN": 23242194730800649656775200775540233202675597323866807821706313015980817450049689426193336450806274780026072878835451600458393952610349663564208170979818834827262822849655743287789154279342187750060682752334039354263591137720448845069358154202631407620757714837065929559179966203904720976823170650636059524399181771789289672121667430829244516925413634865662465171931780292245164081878399390471586371297493306239281353812312325968730748657735698649996152938198667372961238983916142254793407596285000700806956335729409138891613029437100354372573603138871811985199589512282589834778271301045228385437833697345557845960804, + "P": 161017173667821622526367617864622003641385319273501283614693369124550309525151657359747838200440650092833079350446346094169824829878819721139600386379869940529163684111577023046210773279749168464606353391602564223720682758771657549969925797763361964668478535547946618675375707846699109613203757337339941079703, + "Q": 144346060742249083994269365500742861817961091528206580213187588434303105110073311873691829908713109676326867015347244599599366979050293956526525425453571123341666673231285521304114864204336409749299628781242031846060919562553124903638344231929005996733877126863099237878214629471310698112299151312528242255703 + }, + "NTildei": 24462860914747243358546323627773893130738821461401341824825345462243925237841933489180433891199395008267429251149636383024979936914386984046495112392151948885544779760414274487116095167246110037323486328775942623587631571153493845894931798269850622106468371839027543105629096126331634821358789234665535182945666599988218770972852864020832184318539691824562743434286230496780946029169869753200212210690535339313505927461656422073430532804915842999599806540610850726389802813802480680519030898530064347299714692209312597254577607740946972333057134302610046801192952574149824526450685850521950623765880866110076566808773, + "H1i": 10050111706072495243999496814680934124377036398016766556993758397032846983391590117026861690183428233637999805328375188685263419492872311552210862921880845503002540327766791640270684615415947597129962552492005207123808981384764802739931527057423910433055458939237948011685306316858844899288071012390694464857910925354616693246209580514398844488923519402427095453694346379538631079523863618523658407665895814194555793056170432586464435501825929495088772006175959000483916365805823515008461754920046768389524079992065653925518809116538312674411234999450853578281972475545603447208689386435339969834138106028771124890635, + "H2i": 14240361168237288068074599143247216646824416105247524598385668199928133749956751997771381993727512489025036164585045407905019041308063588759262145916854388110347511018859896750235599397989884993301952549732155614736687037650588436806998093798295537479731407457538523629128380259771154471333514983408120325105539209719539410529069810447354248260337431660473458445640003577244952970155697124223326049194622369634632061010178070181535453197753358681130352538997272972246700803314895934758789788841088333414449403623275628945443653201156849591802964784565324456501704948791001115823645656236463536974557068156273049934353, + "Alpha": 12973223416718265276543094319597737135880817758520547699855171994913850577229036245561142342726721549628072360908078370842222217964111854036231190108863701396573809741718032125380884081811136268233092886654955645982113169626570931827244124008255043238012586786025925483487628216501063632074260311533680816475001345643503486119583369115522487989683748783410663423858506424267007600167043387779024928701473003243349861105266523923145117533904155246094123924083246080334683568210381176752244741844189601550259087688101159063321204217058083328793722325268822386637638841134115712903942485806843125188547764440697352266825, + "Beta": 2933550949281255715481513143636684273688357098271118867477676858128493782213012789887202985438166017438239382789612753878179756385192995303788146369289283263829317774531152568184088959908395537023984533674841281596186257303870883742985602401587488297819239875766225794106378648175007552763966126326983323720948105327353286198373302884085788309479875410221334578495667848070023630367070958705395075434345556214450557022277297979853380022975824660344315262103406563445992104665285416934181640684387860701996435030233631156121170487201036480438734770024721522421204104663883737929814082819064453902100974781489291368351, + "P": 75195193317352594605418632095719173223048313126386625279081115009963743580498763056456916415080261162715744114963810511041266297124242372748157905304325970559141290619318878369665966113184287197172315656924959104034607032285007311010185478343102575814602672742613634807218147433069590759326855168152019299789, + "Q": 81331198962095141196674060681595439137163195168077511727355741071870348635329587030619524845839731305172637610043787212265743219238365518057655490485543400006043356343800474951368642919872241699442958368914028317022408399288319598858952988073802103260724882216450798170738637788271032928983885765684312531343 + }, + { + "PaillierSK": { + "N": 24635746882601051472177496856996850384505237002204022414903626773909729361565597854418768496816897940448630169348253277874213879216258404131130555697719637586235056419719107511396508095296838196442120077601043489143766924337782639383616462750259557656691164667888859967526765569771446730344677629914523316000444329376590359887784252246586793925486791723243543747893784208473717645811502099124639137662388698917992002753974586389214497867816838996438852946560228162243317931420827422894813804368654162447789560903699783851631762964891176538877308742405247587933132559389126797717345505900863655908278046332908315499897, + "LambdaN": 12317873441300525736088748428498425192252618501102011207451813386954864680782798927209384248408448970224315084674126638937106939608129202065565277848859818793117528209859553755698254047648419098221060038800521744571883462168891319691808231375129778828345582333944429983763382784885723365172338814957261658000065077562397884235470030028203033538770995716352181372402086470166028049731747261665981796338208761902029142694509382334388582915371355608058899470305471777691762896059281154266381723150220355806571679654424667288517875465849143025594439802987991549567082226031398187829943889272329543844446572626859268896378, + "PhiN": 24635746882601051472177496856996850384505237002204022414903626773909729361565597854418768496816897940448630169348253277874213879216258404131130555697719637586235056419719107511396508095296838196442120077601043489143766924337782639383616462750259557656691164667888859967526765569771446730344677629914523316000130155124795768470940060056406067077541991432704362744804172940332056099463494523331963592676417523804058285389018764668777165830742711216117798940610943555383525792118562308532763446300440711613143359308849334577035750931698286051188879605975983099134164452062796375659887778544659087688893145253718537792756, + "P": 163460369974826440705514174662949009977520516439071329942857631105315772985436382454982935507143405068897778874365987222405487933545534405214049775023862225745666501278783035529245783452075153398271280683418197034314208169150226108955250172348396091465939663092045169745405438732377680629223383632171123855559, + "Q": 150713881819764976138678015517777837967279774100109673146753637036345773362571193337692609478827770045035938490589834498031844103528593375107004230925422381114125638023482078832804574616138297436374920911432252240281803864042664378733178964080868397333028444234285252312052288623826887590161517447018653851583 + }, + "NTildei": 26952301843143637282866149797084711499812123886649395253203935079954892716635012287069597740882929584147084078842102570305553223265651965517698460642753993177010911803776480967972569645061058922407332007731875727831446192019223485471387261222989425576723278371943738118392001189004304385941489228070346488712290802294597234526146756924141041718603271884504366484309043350924922954983414281221634138039891694805025219737053771766703067095030206014515414216099919878243255679194598668517425955488139864643616192529281487814170910272949729936744658193229259410265540610217896999483463791982710441403248992753863657411369, + "H1i": 7039533162678942927500209993292727850895372009485838787575679546863860902464664073719022554280663741270495625962519994057947786404908609202931303662491477271027538713978445307424258608865385413013781216152813719631902620102779316387787835766065217303491718792291591533404701933176628587632697059792054500151533149199882139659970677179367462465944610816625277899265889982254821608070987255987429355647021736573111167091171507360305828055593375272217792000444689910177761863974036143475753661823704356235420861048525859753242690687643212000706287918196623998213842967590811141573146879354921569341703158405719731460064, + "H2i": 25056022363055830086822505385398905640575301517187597132837058494444904586542165647523300931483325031880577675775864117380298146643596144843990690220614817945554655184013561868698200009014927839618305609934079450880264477839073883338885947061375684387326992423507622720321261448327980872523174098136789839877017037206959048600120659834867005711879010652652441112014458314580694970790539322546676899264966120324026586625834126750837759913648516870020205959401619613107702595243280970598378481184131588087360541614329722802690843591943364481200105690059785415903992824039861740448327355539277969171355642043227693826278, + "Alpha": 15664436892783907188077716879684694624426368673157864476047004218810655998620670324662009620479505310479942676230561323041766561120292249565945133725696166570271772367308155125103790171479966945084747038748256366590448781732116350752413555318512255176345249630587133904775573878415255401454255783977147877542540024724057239467346873433087225801690631817431819963995822123795597189948079157940904783108906698371904613775376721023811020907951741244281932220077795189252118652049763841679324405046714901053752070995206345821385282158957102974070078862166711552246002897702758239522873001347706994897109849724684946339098, + "Beta": 2665901088363227302312160352770848138951599750399544398720637659565888342084078032138667638819567898903633960258303523587749718496504218328479167808708194108430432038094476698834844369592494746708900964366430376771787135045596520705846637874211657423605969246466726662587348957905895144831343894139022857466113116906832849068135662071588087132469701327626138826371300483918095536540048889201637003004541195598094560941923618402669220881497138479606974435801658922631185398941360673587933642704496585723823436996837157686587331185087524635964116445030834015766555863972316746092025819742143377139870451085671520967415, + "P": 82256981148897906812181636333752857057434721490890552129674637147931516066621458172828994294723462311979035516250324201776030104883746041922693838599992462232692987148674967764755276632912586768422762598846491981097374171851523550935427322526022029404381011551880837679780993794782816823463228433498352745401, + "Q": 81914937391015439851158983714133849591735046515490096603996072190891464525166376330908753495906866396396755293430632803693666906909670706240028942243581961947168945387644645074808091484110365503955461469885064872566032315155842155302882993810901636840036120877241302495604535256258694951572367118932901447161 + }, + { + "PaillierSK": { + "N": 23651352943103195173266914781748221649604716487840332558457143873843925264041224010514764563116414981677513379015144035964456499346239206009846091918289572027532360384577201131123237726608102491162140305336568906279953131239707948688758329600179062879824171079558989788806671518219309773451259705788898608150977599663263101105169642829991493195154274692835011044905982753766409942009874621439471731500080479353114522969648877505524180210115387522237190430334703425445214365179078324667336138966845236015234614682321336024368804910127818843797609130423879118547237103373273556120117932872585572665449084450944107179957, + "LambdaN": 11825676471551597586633457390874110824802358243920166279228571936921962632020612005257382281558207490838756689507572017982228249673119603004923045959144786013766180192288600565561618863304051245581070152668284453139976565619853974344379164800089531439912085539779494894403335759109654886725629852894449304075334898694302604526256780475238711571025095421814000468943011217495979892291448642857927283082760578521803898927533720961469088640735761549580504592731732370711512136038487971859913944039400382063386006600112015146759552170682603103595141084978760624183291976897018919998749623955857788270147103951485064826038, + "PhiN": 23651352943103195173266914781748221649604716487840332558457143873843925264041224010514764563116414981677513379015144035964456499346239206009846091918289572027532360384577201131123237726608102491162140305336568906279953131239707948688758329600179062879824171079558989788806671518219309773451259705788898608150669797388605209052513560950477423142050190843628000937886022434991959784582897285715854566165521157043607797855067441922938177281471523099161009185463464741423024272076975943719827888078800764126772013200224030293519104341365206207190282169957521248366583953794037839997499247911715576540294207902970129652076, + "P": 148052451319258990481048468792492479234326478860827126083914804819421405702344546760937235528205817934300163010595803118754422940596655500770241015904699291326992652764097878200911230954712903198747375707690263703976654598820758744508484878100403690458641709642163444927967024601056533755230402445600058035659, + "Q": 159749823338633062175033410721577573869757370346182980936045513955028751724632788962679929806353504375206562103985632463831579988047208922305940228966539392695197440338004502746597019933331568689715225774407042026873045969941853892098842082365954179722011439937072271194651660359813462369924474102373919492223 + }, + "NTildei": 26045394650152182790778621204514942077976898328189874668148855889269744286021446955036937171968654260875327430903960310446359750539784010286051650827824472538547879537966937566144137364890682546641637071263139698804130052289758243894992156621922152051817914419226738457584644213378352547793456576635860296383034738776913137567440831023701130211377981296513933199548055530672358988344822920856996660808938127789821947721226412949736679725523690334009285499634446982731085963181736273099785033971191465868401380101296271065994001114076107675037814092348546554687910493793183024499528050710942088563420877207702222145337, + "H1i": 24959911197791474689211029465596415507814873188767131410439282910534724899676963445896827387808986385756230519782397491649071384006141853473321683153259736359624814923997027029410020129705847253599303387273142093681392114734190156164784136706623340358798889577726594472406258179404908139771525002772733681301116338738029360097131122891080307723515153011439660255193514116009408957019681897041936993754830919100688997946077369053330849481051956890935351244703965969048123920746262964543341808525935412526697612077342868245778516826204312718956152025126512285626340738411580280569640857119258877427339852354966820979279, + "H2i": 14196943166558719414187702205052397976834393774062534830443469591062280008813931827308005860673698786604716372024846752281316969429195560311190488129945120017324679238629646479033721762193629219605519569537508792582562431772472458536263417785954730527119764472995926776324769247285082698295114870841420387956389802246714872269592996605604041583799299136915436423124692175502735276360651454580336279756384602230577930003578116996621826392485948162931608555605836458254888564050076695195816758694497843995986061565981454574099204619762230572602792486678288833083892755568745345761436614848096747962859586686569659899757, + "Alpha": 3703953294838301514991916984893557414618163866536327933615268027522035761208678815276747692629965418925523857938314193104182439614212718354689700419956911854034597918114996413565895411830920981761713126602363455230847536520897662145020727224256572591715411400535497897764032530924331739064799461680124862326554744128175562524014240679100339685181948936771580496987841140319022694664395062277798801960146333144218959214846288137008238739227636396185582538662812741797048409746474161243534986116724055842771246714168461881361109960436358504312692565935655393528180921659921559789208879383644507042901690768300420571361, + "Beta": 1099192752500354711752537437363414689152478490644220971702185990436845557841500436045555495873214838477669168817058383492000295618267978034429525445827063826497937359184484261016606590654673986794559826383598356758958009961258413554131429255863634647682823332395296277833700374118155253728536620625384456343623946415929450474184430187522983701735551222961969249194829847035018174740886698139080867651219652657123266725345792804795953714563345027389498163129630849857198000161742749740309517144949009721404757661215826926157137549372511903625285710571046174204191898516079047257428672737709573414412607114490870889064, + "P": 75948837034979782857551741767588980177265204685651583322702944251384509329113534044754135015071634837710267900297555232712435000398853159660421105216464080569618475889659743642440414003719647799062506511168226089486875073041680515393344718526520830419835001753813253763240392355055242429001570325448245110971, + "Q": 85733355726554595309083342714406348886387911389338312961962747076348057175832156673436744084540651764156389058988990952820393122463235567457674077536057489474713427763623277577016215624190810653491515432590235500024277695157685887232690276889298295470493588155574288267770253843169446762796449840380512357479 + }, + { + "PaillierSK": { + "N": 22209642363557248819917096497591583078855644873537092684659237570950005487071351730138698413672093796692876071510402125173878574469041669415872539252021066922931069751625485124067920384700625846093023655894231287715730546575691001958194456736027522822603194778614461865346051486201736750103274236542212514507014172187592959443541680966314853321816437925934052205764879462098580674481066383717135260818045969621940405728889833930212849505641234939638279612106030540516169327730638727952934041190688134430079841055862681593838865060100591445550085449238428175629135314406327015470479885177628441057971831787893252607369, + "LambdaN": 11104821181778624409958548248795791539427822436768546342329618785475002743535675865069349206836046898346438035755201062586939287234520834707936269626010533461465534875812742562033960192350312923046511827947115643857865273287845500979097228368013761411301597389307230932673025743100868375051637118271106257253357638817790122986997448833353259876141206826422440098361711302304103357046184501518695953908770534495140685218546654756861764836739445223319673611685412410607524854758789201081613484428290377880489535645135653057568789667880714493255341340573451713126812029725324787380599239666055398099203032592303410085322, + "PhiN": 22209642363557248819917096497591583078855644873537092684659237570950005487071351730138698413672093796692876071510402125173878574469041669415872539252021066922931069751625485124067920384700625846093023655894231287715730546575691001958194456736027522822603194778614461865346051486201736750103274236542212514506715277635580245973994897666706519752282413652844880196723422604608206714092369003037391907817541068990281370437093309513723529673478890446639347223370824821215049709517578402163226968856580755760979071290271306115137579335761428986510682681146903426253624059450649574761198479332110796198406065184606820170644, + "P": 160620724093805862596409231804750427174716115163084815753975737643031519664995214399428994461475706604470904139763392748325054642497137867986551259350459644790756673468022513807845438307440915348175585414153008052985104805441946545743188771641948635127335321511997041650679671627016510924638616327627426802183, + "Q": 138273827918907606950374067803583142359308157926087193287481119847342440723702166280314358539029194027188131152033131668164265189665206625012381129384746074510362944745037811981861634026666463320925184351438367425716180918897215913296213996449576114248175933443680399058601734218501133934927150275659005634543 + }, + "NTildei": 29703526264608072178960188737797514280510964970206681797854189108356168805091607153300080823980668286883277325786438078696961942400895679179350081438490115544469019183647226458246380249572189433233549203545595036901800568077206767670894474979553971412404930973040305339781753457677415938896128646095998900518698019928141579731957342518116842552213229575128106810795355943233351983204700431310193268553895217886168153556298116696329837650966172966836426887820340228980651604429029617462913526155290087185238682939677780972756191205419189880037401764203590337214313417437508832893218167071375080600825313170014975949653, + "H1i": 17291190353490564634995940629862526503367246813917974520603059293027995721444868851965986227039796800012584277095282533682294057043501899189439972858754415722943010280075897701325567212327319975896003941997353162959610234200453846231565645701637149465672078877075367697252450283397545667977470649727680703977148209958779215640680587687647623108241285695872277109911965075999008820239425588819079675780617845606657122385083776897390496702600211959384348067494050112941917581516759622066144395695130705033696999762687450799799051398470309426516757897602482174599877270142828798058216642176186694463360158801629844477595, + "H2i": 6335871542931615617990526691318607172232243668916853047915918485835075181896310556624213658848318149370008123430692494300766834429824320521726964826508444924583654512841754045540667170211188624728143905819827111460662612836211442539169605031426871365265997579742042774535135755922090116707452043741761934440789376373673508031126358023383578340682076631871908295857440809378641446492255602557259905694975907632060748165503875367764936438514938891928155785006065148986822026020332176607336473255054848127123410842349827830744239302903974326408421999486899016753392382744211380238407831318581015207603185490751128038819, + "Alpha": 6313523374845653787848653008919738566438639165906450614476217315411888551515719578607701028004011653520456322786688101158769160594837055717499097249430289709776508237118697328227204146576993169226626429252711616441730302615612177296849216559652754906753498477790563387471638184629072478239787636295608254100113355156384613462061886559786499912967447002442462835767461549570545722869656514693641664741176175967825858893535570546168945772258154594606755177878789846863392693181470595115420363894893633593407463799469461733474366929603779853091745006107877083882852190071090447301301741716415530518478231284750808396014, + "Beta": 4507160880406031411213316759148187329401590932594197035716984340447728617491534623681131184339969720220050536799007023898557665686650838464650481873798728860995502189375681527364039268931195966093628921186228042343132190468870036800450310901148773199465954330897683666470438000723062710172624610073084572756719214921239594600384396684505624914133018192260295964651722907093867497261987325279858282622349632211429699463015050713688175368310605358022854133440730984366735536020490956948799420182029196732532158189071059929154710826207782529928763276317934890852252825605572878502706391129823696778800727988104310311206, + "P": 83753826644514129976337808758305334048078158827924782576149724599385507747355035079620148238094125272631100166931865050429422183579166942324107083210214427886295488404836328859173260447800829670929038543251773518799821869085431114319381498563180774506945830417874588013163951742656738393403122660881026893789, + "Q": 88663191446410320989173950348192311373189757091390450729026858450923834341976401536582067033542016209494118343990544753108437843214576239681722036691526067749302941262487401612258810583984825206751734467944278606692940502976259270923368889462670618772210425398607090721474915267134848280210662950242811847703 + }, + { + "PaillierSK": { + "N": 26213695928440677705894825772568428308723164707347446591680826336537114495148015767834132013089456019186844139183289408431429210540624476649987553139831703766737157273370693064614988113888688047207689279532192211376852466423724690103744692478804734865782481702992018638231801781898190427600366789689988690318675537153417157561465065413926250235993828283524059611594304890086216517992913177618795268773219178906809815387465219236859200407212913367531284904246010679294124087643681176345837528548896059486364621508256602534933142557018359766874141612635384710781097169305219572525673467778647112933535000370146791254253, + "LambdaN": 13106847964220338852947412886284214154361582353673723295840413168268557247574007883917066006544728009593422069591644704215714605270312238324993776569915851883368578636685346532307494056944344023603844639766096105688426233211862345051872346239402367432891240851496009319115900890949095213800183394844994345159175610462696554722285348852481204133852464329120648121892679239930803848520227423433695454596966134424048601663676576255265086651818763189313601805305958739577012864096137797513338252332254958270025050743147382283971541739710823312495517263126329243981174884705176721157387105442835423199577585670259921232014, + "PhiN": 26213695928440677705894825772568428308723164707347446591680826336537114495148015767834132013089456019186844139183289408431429210540624476649987553139831703766737157273370693064614988113888688047207689279532192211376852466423724690103744692478804734865782481702992018638231801781898190427600366789689988690318351220925393109444570697704962408267704928658241296243785358479861607697040454846867390909193932268848097203327353152510530173303637526378627203610611917479154025728192275595026676504664509916540050101486294764567943083479421646624991034526252658487962349769410353442314774210885670846399155171340519842464028, + "P": 153127166581332438310520143516385326126483492567713235985197261629937813144159736532556155935542932400915415638894055561559039393206506715138655810500926433903318660850500965291533452588281294549868539917643904348505960828584736020662755251135406103504747865699084465420051482627617294913572225855958405149359, + "Q": 171189061442715678583847565447456642162416132715050131823749148594671007808298594218848203643743977657797196421218011164769987710368880273765425483133166766236779698600904616027627571296104848396445980104317933618484098249011977121220351835247320119313999534195781664790847774265358971620807603173668543640867 + }, + "NTildei": 27379961403744167295912242225095237617638951801557547387051269257520457031210413715939931790754973266466537870803816292314424280065496506709454503499442183261206231256170689796298328852681013257582491397765741608765573139753333535953972804612422245235409953765777197598841942060027589999774070828591363752211922134820385573566150886987517408090647696990073224331213767686182562971993794334003151176153009418575611368909716570570907093953842416814441768606369950299739392058260323312595145184449077054010467122738864844456276765148876274670907660057159426982565465331773172012343524531877482894579153699516444083063057, + "H1i": 16626965275890433529811759056049869939902849459257039107638638439909353307412794212668021825154083483636235553987427956134762634190488421103487065251830795801596913615064842332290920487223756278138422212871130203258620082436716405484588968008884706230186188198378497108637665621500812391126234472902356159614619960458813295871468684884755425931001905190222323710591482891532158363724902828577554316877826421261736064145190090239115547912908544859375725723544643897241148512902573283938821258936041652205186556623769523455307612323653347665615023770648611898212169671662622151668941992106310100847347131949729584914246, + "H2i": 8906084282415161697323497430017092450283671015563013565917297081844948550443092434132187420562870573529295453968141573970683757283950135132283045411377248807946736537398366381274038553650862493675683293949666283346447493159358349561410181410523475328218273839488708246837795825481208868686976332601244741380841424120567072122918708660978238016050832208589868791839029399178687496418374059841203000601566915392178906092662744888820986284758028119231080490447352125902596021182756026464181058219240660669142219896695655817723160504347202269699949479131109556579401035503671907859794104737249921099247350937066164223477, + "Alpha": 19362142301652692905581336423541877360572238544310455635585425110789588574018643592691027576467237357698982397642419031145395632071361657472511930748757255447268552564444341982307234168240267738026985827060311972677227231722105713227865893975116969677127685397487138638490927588186246221634743049352385113448841228486875261155852978271222544572545984855939762812683584380250742654582079815603183873785646395667946855509976657070660898988926558821916798600041993164180651583835742382073720358326364678372645994305211601432338835028287757710540951983762440041510421397737961744355367967738759693780887766385436867842096, + "Beta": 6362857398393859223889614928799144323541484658811219822494676335656223075972319990613532478253201626387985755175912872470112258069036556690243303564051004420397929492998047026288572652081699407198608397230736923390965402480297797265839400830409573710780313177253370295775104845493325474875320542957364482576400912882705653843622660078780463847936502890732196042958262948280758803235696625703185336312299201291520302369154249951121642979434553255243236571678600873578004152959257237775548373329041053335692039795003473584723752877164211259738037618359184771814990886038632785240546469466455747709077866088303692664987, + "P": 86827196060787703177766811228861952522649327977214560512322973685588118756387223893165421214432651692724411642117876481663642621142033268156549356736958168313729740706672393069877918715005385682615224836059548130401068153342542358170067929423289586010272053119614727099318025816463430149675568278827111970439, + "Q": 78834635476928972835643074784106746741740760909579612674285506203242804577798653784106589670858156207329885493261099734066676886838103236394735989736408641853305400315457060858037352320256769282827246524978408674841976955289538451332175125873002386523645590765260408353736136094749838547936815604719783850991 + }, + { + "PaillierSK": { + "N": 25830909043964384258374472442727155134029629162535675461622123755779908658153652556734553994813755341435930523081631106521478315853130541302272236764630740442704247177126473468530750864571076495627175486081090129958470195323104902621699582736660149158085909849993667711063858024340962659553640603132631783889658303944792530621195084725549309412680171792553429922236226352769304706463725537826023703793703918019805456724046507601809755834714693420556439768207084763168108781468894059039512812491093633449112544056607185220879140564783062709642971221746142490492863568973315333571590992312313739255361359759396249538357, + "LambdaN": 12915454521982192129187236221363577567014814581267837730811061877889954329076826278367276997406877670717965261540815553260739157926565270651136118382315370221352123588563236734265375432285538247813587743040545064979235097661552451310849791368330074579042954924996833855531929012170481329776820301566315891944667805815281148304211919727284712267292031459079643070389500510076838544552501960721547603995064900360713638678824811232914434128133886975027711975862860896486577581334885276658879937364960329435122406157642345418711766248392689317885698535778773982456050622940902001076670027161106834364233573965528333319958, + "PhiN": 25830909043964384258374472442727155134029629162535675461622123755779908658153652556734553994813755341435930523081631106521478315853130541302272236764630740442704247177126473468530750864571076495627175486081090129958470195323104902621699582736660149158085909849993667711063858024340962659553640603132631783889335611630562296608423839454569424534584062918159286140779001020153677089105003921443095207990129800721427277357649622465828868256267773950055423951725721792973155162669770553317759874729920658870244812315284690837423532496785378635771397071557547964912101245881804002153340054322213668728467147931056666639916, + "P": 175547332131700596332643985411953445364285396793922236397152531580104855525666309014330963176468101037134760445009584379299945261166882761478986136659800393298707163157728888421063097696086212550575996915466014568022145609757912936404396290800087234688478752402915149973028638026687405021018235087872545721243, + "Q": 147144982098533416438601285567931432731823477600221545060072801035522761833055307368597532627106016261243418921387300756680942317280036709022029679821562576896246455641394617300689840065086762028291734825856479815433462458239771137467177859388507290892283570688596181445222299963412665505875976740467037177199 + }, + "NTildei": 25927852965566581567847583625399477554523810258529336226969267129620173802956991771598270359464569659720196782169590231503225186269503038179712440562368263745290567251484099508531714812334071768270634145698532798140913504582026582280062026377559466432145263167098712316151340044267651404932505548802605445652408337762295355533840414032330239681364603235135737742222937840716431935223017794550268332318031326298224071166014739058780985359409100770780366455409387736511753499262480921867134321418868356130145185757245097362914104940130381998055734847678903943371725446192349148145538700413417918013758433169686184580741, + "H1i": 15804523353135876800475834349545491762542778230982997814519967115854573587892273606606486737801971014062097055388318296506681468080265720750356187031802356097241870617783982744432160922800283091417881769569860714241279131023688824239530238554997760699150956390123641040018612438369973066736919498014236134297670733858689257533276493187529901993391466423600024070294080196614852386557852370082689300392121503353941221545646029701885343993689194702351533944759744724518348719587101542837988635475923444269032183968111646528649240259201471919574068772947717932371207319889028578670276027150358746159646749728244297522136, + "H2i": 11025329598468365524175262704737607247325213682386502653278505417689391672261132993450693023621559276315684910512180340057935351122618224938775800916738509269622785441636788277562666890499819662915962482284816564546044985934321345329348547104018934498887276424361172470159198193542646359352675253198973267682821784285274373388060455556474725845458140198866388265987582444955048505999594679133935006354809371204895049813910311891254910596777362465048314819575013133814166052451505347954373436752810836825044354575074106354096697001260563209980794048529049406660305808048823495589725911405995518536102269179999676180152, + "Alpha": 3557532144045049170195672688302369964433428746392919754395112964523048777617953657220760780538423782271976899309766439298608725243959078086794455828978916806024315336573614553737180675361515473940613333454016338984672520405473037930759516997425942379619779206279815318094386347617421243540736120035213874655475175596105431420677619744425062027372427841140047204566784477970184836921393019836936127757306322642157485738610255958082276200067672673526520895718282493883004988977693602873907920635551522982903124092417988458355157338131538620341300023197953465753193313232948507327875381631361325380240061579764902703294, + "Beta": 5002241585952709666217520566575102327888547287215359854276250959820482003800389794724621181492737245805405569786397540524221375376908392648503426879977481874610197451899304829364904223400308606906248693014769679016503415660207820729531451101242391418579699000963533605972011883330214409543795161925000960123905760362635192722310442456381292778067230578424832829563228336898601808199320885743274451150535944187557900414838506255110392590404716547087470988577758116229750697049126640019646280591577679418409910333263242523335395228302463805123271470600065510940604726977644349961029255585110448391991965095290634368239, + "P": 89332740299498718655963563832552296139573366359778135898214314648531204935828178034374657506120602093474597211532752889776777493722481014956220941797247666018862786041892148255049671649072869979549970411187527143078130033949601368083930942405040570739588821574080621058173042938029612493224745344469450384031, + "Q": 72559771699156286285356746558872093708436613117192001800425810368270187509699484728295568888016624079620077087141427421813836236856739956793849792312548317218935978835865309737081394883719499192148881220226823820473073109676277629940134600850661998068260604337107208545181181739086650717082222335821940273053 + }, + { + "PaillierSK": { + "N": 23065912498625363368784418170138341778826946434482115451319531776152242927251863276552420115757503337592758574390309515048711782597224042154721218095067334825599550618015365179867223948818339233249952917156805870122840463381706668679064240666007277296654627200222579128665223752794520653512708450199286865986071009288476462043006973277988222014837561149352032730672220394411196258353206847937373212547323842118258709342460170722253484057285457163985719256092911572458679082323970717387764280637855658903845136325968590782831463386794968958387973532847000307460025371001975649460405401496810667270775429943042292382153, + "LambdaN": 11532956249312681684392209085069170889413473217241057725659765888076121463625931638276210057878751668796379287195154757524355891298612021077360609047533667412799775309007682589933611974409169616624976458578402935061420231690853334339532120333003638648327313600111289564332611876397260326756354225099643432992883476876642127334833657305861517249280378117681052754567307294587673307446358814265874713365417882272769941624334919030873172295555977612711241258176905177705369951366800512274013685977079130009823165361594855060453545505944475212512057372224875585814844262486470331817627898128521743969602188578199448108234, + "PhiN": 23065912498625363368784418170138341778826946434482115451319531776152242927251863276552420115757503337592758574390309515048711782597224042154721218095067334825599550618015365179867223948818339233249952917156805870122840463381706668679064240666007277296654627200222579128665223752794520653512708450199286865985766953753284254669667314611723034498560756235362105509134614589175346614892717628531749426730835764545539883248669838061746344591111955225422482516353810355410739902733601024548027371954158260019646330723189710120907091011888950425024114744449751171629688524972940663635255796257043487939204377156398896216468, + "P": 145206505130141043745569711910205826363961151745553547786026399755900805490941129590997457812236915916833678907669888898626000417234582131123919324041778858794517905287738137556843409002835746265171983281404732144968652497797341715527783703788048505203219267650381902860783337984712237661821621754560143574207, + "Q": 158849030062066329594088954354981689912843762244373673751579405479948837969548089814626328004251161655885147186120443761881139048938919807439317415697322358253421274302631555282893499680861652619026822321374148516955719877108676817836075084609200630627117578378653082964366267255054941669749431032083252591479 + }, + "NTildei": 23353451403880499638101740929964993317434840359259352386277101729520289989822590334961455699104821366961299902213597254079779783615424581373386904716746339412396054481760449249852936074869562958240053640066215910717406723131269261806579317387954282397289066249422902157380333212438848039641276165676172326960704513890533193668337095980657188250419993445153477277891847000595907321059302104023857014870624252509928117216258082572531311416230778037188047453621163960521775657648034223864638114392425244170761168192178325842127782055425523123854135192111759729339337216738183397069843572807322741894990493306486444522557, + "H1i": 13346824370400119119869025783756508602554700938327772269533359845846156419250361724793307558310805254829539398247025302437265526989842520342609203007009776212372850128053543206244441210388906585840644675070196146298804859467907152880797456961909323960972976449383929475978615742990155343306150115613607913448440607791628316007854534184481947646215509957450184686433872692396297220727520995333811927197936470912284016018460822902146743527015536598977986242231111609054533803264628732117169472967743164897141170622447131174280474761759891475578895655790118691513556635067197531816497464123133741313752010598546907012244, + "H2i": 15018166569778090235263484123947046494757357564656366310054592788317263401298594046095931598107346648190306996355581281595417026833571915270893607610243344316340231809255808361825681652746200432583012086332428775824694014996961509848261586723901467731575983751097148360501439720865540838261741844323260885910091672899443494324358314145389535315744930578826750100186736982804552101564302773218019238226240813779237783181291080600371656285410141670086815083541406379617049541407091966929575272319251074959420146596716918461389623225255886372435675191370065772841420920233053572811381648395108599128524647731056585588671, + "Alpha": 17633755622675888000221033724237197630133716600149748330660531686696473309070391458826663610116668841779459508016233146818372427704957780418995855952863915010837534885598245583731226556406829370901243938610996616309625992867391023511128919222814759527534069352447624455705179225379868550179275522414232005489480830973879513424270089967544693512069953686883427990802969942552333504791423227418997340839909910255900981003278864323430151167874753647487100290884039974836618543532086674331099143133079644696557763013403100085125190519923269867253051214407736759016072563688446653173492353270253978874341469904557591823130, + "Beta": 135489918914187386623752132466977672845085721279427965155184918986537685337367008480250714180328848265129006028147346164083153986529702697649472831205356630626299575022545660331157314490039896182556416110810823877301030065479847688367398836374031817793029657001388902356613574141436271114432658477931948551672773956311438674708581806722760784716088688910830181854814534617185219675071421860643496939108873969390301357158491496901392817372959381332465530987575185160667817943781369362163603735567363694703326348130861214906612390234150068056207731488607347103592216353411560567608944468556325341503932719467323578307, + "P": 78108266215443603792796687456594460425943062611910425499679762716684392183095593487699350311927576866886413115023746697130128270711047006006018748232515676541636830129694260919618760249886025647045393965615249245369313081725993284581979630692934347035635099755825120784706190580363532110043862172181948021931, + "Q": 74747054746630146187267388949903892214579999339143774290424815744665666110372195436872626075117773822145830339286363617975536826059736738503848363888387233148745743980349474599108916534491768176879594827839882309631094664169380683016974369333652432510913782481537556047237741478782413999367848391175404665669 + }, + { + "PaillierSK": { + "N": 22606356688429172951402834943047148706681707438307154181872479362661390966910372081065055234509629709347440551663201410375128902713010513207421719067083956779722194504828190765598854317110955335372129732360219937162501410160322228701948487696323490746588479681739955524182022974929069786960452314454436300032899615497054658629125342237672800419583493569372335018384244598397217954811155206265579579894898328449381470397964301100321626728624538568526186173071609179168174164259298042758835186998614673586764053792895986387973923981038873264966275289012488606801035480191814526817970869243761921090389132316652414654809, + "LambdaN": 11303178344214586475701417471523574353340853719153577090936239681330695483455186040532527617254814854673720275831600705187564451356505256603710859533541978389861097252414095382799427158555477667686064866180109968581250705080161114350974243848161745373294239840869977762091011487464534893480226157227218150016299312090781459959557667330141569900635244083477430558345531993936865889996718219819327155109696317551074158395671913158179910835539673348647805342808794945729312363546167708989226596929722098225103478706855509271534122535589640177558547253229033687213749045577023669914979645915189351289530682569530101567858, + "PhiN": 22606356688429172951402834943047148706681707438307154181872479362661390966910372081065055234509629709347440551663201410375128902713010513207421719067083956779722194504828190765598854317110955335372129732360219937162501410160322228701948487696323490746588479681739955524182022974929069786960452314454436300032598624181562919919115334660283139801270488166954861116691063987873731779993436439638654310219392635102148316791343826316359821671079346697295610685617589891458624727092335417978453193859444196450206957413711018543068245071179280355117094506458067374427498091154047339829959291830378702579061365139060203135716, + "P": 143969838875208459914424148959304744690953282434224761631629992198928651712793595639569459453861401362941460483819067373683364327397199217171568947789811462392064610509096254004612299863127786419119412357852767331632125644047223568929560901362931724655215581213925186559688582310613525608018395596527210141027, + "Q": 157021476616530250095583428430355873622052119983249140061550618324557523104925170987355810221644291984291693122801407410278440730147992654059006539664207825317484826657866370775769693276042690717437684021332200513273553265812369340919619881191489507718321807823842000428322995102769692903309371581065001378067 + }, + "NTildei": 30470542001059311358544864581700964312452286815547431850428048398402842728540440455199013303014044028998869074106224180597437280749216708451843985285371329063323499570461553904499171482315318438695844513028326200137011051331637341052828006382974574239930417250086992073114345872915956311477929050392742709104038398139457631586268586206994972782270146778605010758050671817865724059055242462751549813548726924547883117888839229533774298607207179507286434891366499419207005677509084366747961633160187861191837135473883737818174390106905316579599470509053184176944011650865951709154983398510105001905623674273817393073409, + "H1i": 21920377456174296746942772243820060533336225642375477937396609340192189441302481420024901437091063306794885485267115128454856698543006477374277457721792117252060048523206361611624078539899283928328719507253785715834321938294926175719016382404330639863175897134271005823318095763344342049054316893723833313780547942147123639712524569636899435970442857758418190751168235897714741187978976954239482419284904866220995273837977878051138406566455476400483032025081851591260870732090817411044645609290508792564266381744678057223166976677390423243300709202311499468521340268480650697451464293207233723659475080890816281139885, + "H2i": 27320902983664162265003874074839421255536093861748050730021231655841895136921344475303774915811548220930067773637762091951862403572120792007420397959502540317802087627271891716968148513878360778068885522106079022473791608143561407264806882118609246000965031034328709312188850366681149834280433935100113451594507183933365173267328149904761128221946579844295521969241069426976955823703097595358780982129518814579108035285241894075750809341395247997610355882061099450897218804460132685552566591309446894810583223472117165032650319816766682069960106339326705210939102930196367215432651504151760114378568285353809654772240, + "Alpha": 15379133801450552699341960065088938208835059422464506850595596859181661925505742069844983690835920379973104815047557337190053720119039213532772924816520545512993759091766363488793725869325215798871949403295425679337273198187146597111512105376022499166836524603715983943452947695869572066285150177107752287420660823107234307539437626709219392118774121441685021149155625487935916578272245195454553610288482723856614683626632797890250032324669722941060879698741843554617721026626451704061241730271849324845862394666439953102647179454085538335878562032392460889214501497031133340602887986661832430090471199478848852793115, + "Beta": 5994492990504295797673478586068760289745106381174782488960348984944700609322533245022489335068218703300204714606826655335406455039013591080136707058393594701991934482642925967630572904949701979904564986623805259765420063144097817203746908685253922269360716267688202293669971331128210557569481447501530706860445747345504007329377783178064641361124116428276616101547203299259462142950369699753065894126900098718527164951665312141896568179134170650906245501503509762078451171028991063659724279048299542916503707638849857947969178626137279173974553776844539461458005858238271552448433053676834989629267454021212520221375, + "P": 85643937153092517214730368225459026780186476239789908423926779578202171035296077356023371800591712838058751759866176672015587492581336762659064576908587420562332478385465212121386209083937917218747177703158045951743314513206996388395301390633569641359350684286536349957947372072491856659071033812316991021781, + "Q": 88945414625765632654998809263255816184072997245375012088994894048181582396766145724296399519584710047473792616810021549967496430113897248152826753893368652530317852232069428501696882410792690201215787479203803488156443976796791311566375947754087336390687376530681554216428265022255709896788812038323802462721 + }, + { + "PaillierSK": { + "N": 27047625628233403022776292783720594195678252715446128599663136523845532462424429207096615718533815074170053211782541707826170493514677870773938937634454126404201741547311834277844043098367773629579580033174700819898159106191401908059996330490494020229459700869321445288797242864565008832251159514824911731947972611278237390474044333041111749935786536646974739230901666174292064992179737473992156216514768089986532818441072244897913507496017162461843020042911344742361184738938150712029645955041247500880111578578308269496706389623420861856438506737291630197981682248463643299983141660021660655012855013626865376968653, + "LambdaN": 13523812814116701511388146391860297097839126357723064299831568261922766231212214603548307859266907537085026605891270853913085246757338935386969468817227063202100870773655917138922021549183886814789790016587350409949079553095700954029998165245247010114729850434660722644398621432282504416125579757412455865973821736619883946406224043765748563689649054735702285037858519322013205203578582003854149515375302245006488041725191389532076676556000022031002833514585325868518809706246886286263166640047087041509591814466384175438834611185168745574353123714613905157255753397612964432649351626761453645419229538602076033046494, + "PhiN": 27047625628233403022776292783720594195678252715446128599663136523845532462424429207096615718533815074170053211782541707826170493514677870773938937634454126404201741547311834277844043098367773629579580033174700819898159106191401908059996330490494020229459700869321445288797242864565008832251159514824911731947643473239767892812448087531497127379298109471404570075717038644026410407157164007708299030750604490012976083450382779064153353112000044062005667029170651737037619412493772572526333280094174083019183628932768350877669222370337491148706247429227810314511506795225928865298703253522907290838459077204152066092988, + "P": 158624571097728235677753723851158840219600988047748914491969395843535797203368449321572791696541162983345796079649185873260066595493124339127921788620088879627297318558408611011681246226876313733063729835578585710660142123702938927280881942340321924336503520773311416740213485696634135291590587855785469674727, + "Q": 170513467371769425918491785763463716268826187522420240692658134422118787819205016962284394067622436990210938911040279960500087788523994060709431225120604125696268007885969528491631428720197104127864219809961332908377025129380431780451377365723497959133671932464403017944224920802119228882805348566927841200939 + }, + "NTildei": 20865245790559151430973000966830401521925796433072469375851656842781765984797559456121221346381902366192755770395648833535459267083250738332486451616768404161454429808504087960302301727209457507522493522509501037767256183182737950844141194431714994067051594036539100376354890160414247723977821668436750774623220660052613442929198046177216735097654379398587066435969287387056672722332328825910986182213743757672588520770990353096722964594458174960429601968515320371244116711340468795030783075217738578928278237932844553248720136726741222703076819772949138693994998825683858017731739214777949396836586920395845955053249, + "H1i": 3428750533975172854086887376772229830275301990289024634214890657157400946874148043464447185889487831704579060503970719163583283904358983641465634669994536043645227683297520157066153104878836762595177298616082994143791340062139014838273198261670166670694588826455987964745962283338677180151652939761613731002793397185066604814081793874777006731978394797471500951291599112332260753331312075606135220623304702636996031015500793299896574861584595605284119815103214469563753920435088960491763919182917861416439916830973577794476255216215146524971030136608358485819437936236699252939899320896803061229508083573248385215575, + "H2i": 7915296610468666163043449932722017525347955723561129251519428104164017586681248400068640566504739562661354444718865258372230799250636823012526506870647105465348451839805557169802865987861942089489037897454127916980764839923481645286551451380784097044259682774019460723792000661926240670754023683663750185896374902940852625547822227777583364176405037861149432701341856202766113701134793765847481331787276918603489909729887149433653559422017386951214047660851604355765845661853893074281143459255727975263988169424044139424690929344475371816114815730063701996828475269503230900747724586767875529486314866460979503420598, + "Alpha": 10849318463569810225379982316338460289303118706839938431726466200230686136543469596201856766839870048292495183483824326476550161311155130055172881943396969956135186969155031257325219768741422613127134113456526898989453443225350825565578373868238991195852307804866733343591570476984765850376048174465384392420677383894639583346350937798176696451693546864745182757107269639712426898779877639073571746288439025730481721135377000152465885241835670432616318664816036239803597091345841277211591437777843405973766005660377187320963296377986476854814809380064207764170325238899373005584568967626966104335787399345949518778583, + "Beta": 1877217056345900013641521178786390358898668762660573059843280280675608895005311229257487934761571724012435501479185511665632221399024343982331878278400827132531435406312101491381329866142745882928918015483167089654879468194029967669856141053310511165347117902738197190224457443771589298625348043384417579358342914174847842515264115813497172161810170287247837045580481396272725366855461881498739989030088423116075327716420879957070115721657922237179628949648643576488605939257777639192108547146223384010453876254043525351148466588737906549348915465558989110214355834316827483833174187210485917243317079682539199157567, + "P": 74045233530739261202655115568073521208666388513498340257082191481174449006719441000945757747454804978788800612900443596941383920601831417279752561311933071817821389697472154077295976718505695790703796288082489821871091456396584809080814623178136779164621248223165319513062426090660180994079159899821715003071, + "Q": 70447633141359189062482826779230870072202880203367932960756921640396535327314233378688089280106079356458776203011690070420800961250548821358100972847771397115186223822876197010178438637715223430065983663067803371647882787157217103281145187337206069748192800331285066136370020353088252112914029905866017211871 + }, + { + "PaillierSK": { + "N": 27713370834080243485836599460751224751253078147815715030684466203607535610809093442156923387960051918128639269383977461254232157620537746435035622903013931401730164562307641344075404954653457708552962479948314585838669398135910811865781025080587885899335724638237023343114180657336000584640592121496149942226349867971156445204192020181422383616785688351042141710075326593290292878174529339531564877472677700897851824511967787874022417738539318554915142702912231616549814998553512260898602171881098507949240494976477817683583314212952576632120447842683656276548458112722488829971334500394824402333880725173181489915081, + "LambdaN": 13856685417040121742918299730375612375626539073907857515342233101803767805404546721078461693980025959064319634691988730627116078810268873217517811451506965700865082281153820672037702477326728854276481239974157292919334699067955405932890512540293942949667862319118511671557090328668000292320296060748074971113007974662539335233889472481957189379546625069059224815036625068431404397961920643080062562514178780931365202308329723062493212551008272919912567873409163838099808944625163757962688212466229543525816337442299089313132339785392340264748662100265526168896952436353870643738872346697383312909246679839846144737482, + "PhiN": 27713370834080243485836599460751224751253078147815715030684466203607535610809093442156923387960051918128639269383977461254232157620537746435035622903013931401730164562307641344075404954653457708552962479948314585838669398135910811865781025080587885899335724638237023343114180657336000584640592121496149942226015949325078670467778944963914378759093250138118449630073250136862808795923841286160125125028357561862730404616659446124986425102016545839825135746818327676199617889250327515925376424932459087051632674884598178626264679570784680529497324200531052337793904872707741287477744693394766625818493359679692289474964, + "P": 154229644507074286568456865191521442337979636658781418499533403665134151425612369121845895860068823930269224527695955672465183273123763082294559041527214376661171898175372174040655778585229739576787417453310313242640853207882512954513577517674544383611342885557759646035889186954092890498582767760002850819839, + "Q": 179689001570700449844618352316483415354458576264910661502543052762349930825075684249593856584251315104852195367612386076570809363399009632795447914566689563689025211127812570932569968363409681320820402638569325814677781434285383148109546124478059555143210354456987896457700620045964886016804597733486349620279 + }, + "NTildei": 23178467751283741082369676287646186324714832150274311487518867924495659986248305894686735348492167965058018020190615242749633280649444264949462951219063700136929807203294247835270217226523578022435366701980485471816238511414661936276050720763608885979205269506120055667305892228180245583280103628285071659347582006786258295374953961019527840845114828468478862865735195360344590793707031779744498576698952934657685300144780594195158017715586499283375564457882590251407632467573978814556618071121863433213315584370116048467067032102750826879501841645837388904200784988018610113446952558546169630426059608162641542967161, + "H1i": 6872927343802218091502336101315040778307521850864123659907772742428117707422219619842657326633062434751478627110125115903024530978445335054737975631895402327914098027590196038200908403588430233508767528595145798337888653339905702780379071159070653959606796878326285170591453178021836675773773896199878513113667938037877544601679608937144492045456567314524739980168397120485504198877612658398322060314139300200535845311284357115767939043034527885975243792431503002469732495618324343447322847704309003757378677377666543182575318033932347777038928518577152508667461165641799688761675384138707688303917792145972873773970, + "H2i": 23165848035094274863058836289708028390462708282552352657821011423856601055530473520962764036637474261911371787742641270401246095112853459580765286722955846661002572890938216694497829532666837770643686821673027944840738996720071357307562762511337466067143168389327988239844322748029161124457175730450832695279145412290104259924736583168290202984275379985727615917318375449043285863555379546340579918052717938628657004364475006243930551096338637508985420586642655890963405774697337031318619850590893433286070125656942871599772105174776408894665901944935190837734249454812764882278065140665500908552054863731345648364949, + "Alpha": 21786713408434347755950464282477174059608830820488667674551372366119411065411119302040027808830351963526672169664755157611679997284430757340873371943455800931608296139899148541359206858577289594934306528797686499426080978137076642681384446827616387481232809098505468598512693869324408122846144807737597463875021520443344343410506793234841085508283557844904146312522258259390399118678921039932071584627236757074517818977154643012579474914155382188296532321134577200237520612864625323621475292135557755540603859606401106324775622184399855610758794419588002519369031123181522275928435189744078942782790604939645453975398, + "Beta": 4104617482599685774457246289911952034164342150253904097208514436398991220729710746837700219014417485431329928575810492826269210189977928488700566210774045453327198911978137667660489039183125270786311301078972555560685840665544938442741899854343625329211143591267052356732611462951955784934890453356846231658007221072797243881272675464780473931701712665205448764812772493164920929800199140094105327827419740831077721073524443105697505567202460834636583999375154400898302817457508108606050800081479410855137159263919685840119477899789431574041640547865442796611148726205570586348379144166183776647352608167081755507350, + "P": 77950060032468343579185994919912537924812184818550559461582869410538670889154559681071056461968205131865281572183498311698324267238881551290420092266767484348359609352309867345676717765760026521014271427331257017201516010033878071203876625010394809950884693195664626684717586202892713811663139192002971483989, + "Q": 74337555806978441938524870993897958506476655509433780149425668656834394012950977946604795199139194270454252897684124101591342649227459762160159168541767298921869836282438244204485012717627483683884200743825731342936797190116828473116032031371458648583476131086281993266446715268278649104188316143532693355829 + }, + { + "PaillierSK": { + "N": 24957272833640359944606552306709201154941495202818855173148791526465944389676122670399386935922593477430983218199240081923962324651914992504434894760553616593003624600158476672927520235067763659089734114897712569632763885009993549314169194668556465199192686655847221917540491925121880095849055008766019244904440817241604654670838290056926273431496016849927431567317612948300129419428604263344082652422846674214115360923062830030083308803488401732168729988083653647427263760943145836849019619521154433337064908474947754307694560751627835372939140763267295727371026391268755152194277250567804579146516794875835929261817, + "LambdaN": 12478636416820179972303276153354600577470747601409427586574395763232972194838061335199693467961296738715491609099620040961981162325957496252217447380276808296501812300079238336463760117533881829544867057448856284816381942504996774657084597334278232599596343327923610958770245962560940047924527504383009622452062298324646542433799521966837917283365195342428130041122890330032363760021391249649445532440270870429682037915198086699784046123770585074874084736671762709760042333313386252279099354665831552698317827655667203231045918199211448012582062804045086408280336121103276477340988975896029662826122161848517979312698, + "PhiN": 24957272833640359944606552306709201154941495202818855173148791526465944389676122670399386935922593477430983218199240081923962324651914992504434894760553616593003624600158476672927520235067763659089734114897712569632763885009993549314169194668556465199192686655847221917540491925121880095849055008766019244904124596649293084867599043933675834566730390684856260082245780660064727520042782499298891064880541740859364075830396173399568092247541170149748169473343525419520084666626772504558198709331663105396635655311334406462091836398422896025164125608090172816560672242206552954681977951792059325652244323697035958625396, + "P": 164559553231576646989435271287770899177316664651787488000629474824994168847019037077943237188891797361051862944535918623606362883567820695367293957666625166723169291100862532485988735342519079214914506266997239959887110153622879189386996782120049355053316434418853530750445937617520924161979014579380348174159, + "Q": 151661039079993156249810851962667965588309500419383997071202813410407730538802726967248350353413135993699422148130738006908853672379410887053266557073503061184009803215510799804832174846972248725514746896616107885715614199582060158388018373057073555757037714643348666761853361158224329332293456599419622462263 + }, + "NTildei": 23830888077520881453233446503988611123749630535309813911690158182225486006405304122358483232326294201928186772561843822490134585435638159893485072504543260587312249629190743400691007576557162172490703457179947224745560882563607379215015331046307554792123656912195037890020765341761126673082675012053358471989270101504227929140569876357092633271803309932007324964377154658713450653633778572579221006554600794664420057899850086646771227143286932706774586467245197049500188959246084468874010357109872693757210139450775630837607245995002063722933357963726441341325062599726234611734698968922117337422752610022880456707497, + "H1i": 14235189201622891436120977458362127444873007548487023655825180277409664430273877832514278990753731755812955981229172184588331254931032806146534908352035731340033024828000168406167967165406710817679684914700958671441127878862280643750269587232414892051974080419185899999583146931679402098869281641530469773983235055884902763802375936608009426963605198729737721850017850154718301396685774021719654977192469892192838633720622491978073980147678648473339445949810420505764553697736397193402939114608542084086607945118903339696009864836172059160062035077752185580313723025308105287434403135251572010285878021317043703104717, + "H2i": 2268334288294646800145355294191026794484014279561150091832340684929246598596194541594709153919718386084237899928939775121256179297073050497666643405402560303007721972677684413404964905770942239002195669984940166835520554646992972161152779346601663585319091624984434724173364290242587194333370182418800364973769616557948159822898588632806999867725354182192286342783127933530985768510975884389249001518558553377984089949879775458842434121943335667415545316231559690036365439279165234702694192730506452775884867471134478699213343533559947809797510068869281921567665054311496428789374424544319441661567662587852289556636, + "Alpha": 9125170002207358039994180967407646100189186815638452427743157659966686658321515603539283891427156630477194039257512467371558207279086218816362353994232739372823202921143558975622653015538681736851604391985076340031121006376689427790602177745767586880984935121277428992531435360534053012589197348655873618502410995034473158185776359321628044411214807542407401305093777261189293844824383381969613127529823897150657979931254655004750992696666044130516086673616298173873272000297635790675715068071661523796174291185956215677320655725874957409097476057671013384016294243376607476998728694919957783392812784586898101609962, + "Beta": 3558285124063019757480563950006414721712103290204397880340008163150130022533299818270145515621347634050406430608742912592932940024221562583498825289350629962105845409872459480143423059508010772255695844085490869508854955246734967705718093246567161234424689492145835275789558368534778295490663486192988948192092340983339459488486371009974762630087451927927350826646176186415890210432176609850937375977298670239899639126829649459424977331765639762720613274046556973250366704139867924791317648239547225160432856122144606720136161987979484775219076057006877160861911617933379143555827406303161698562548462610726257135496, + "P": 78541377945822227965134753765044920665659042830122998517037235353690780385538242656818528297629828188587855624149558638300631699727495877587991647109144677876625317886817462203619158094774186226693591902177747304097114941547515942773335631295363405147531681430107086784483053898906218957574402499439722345961, + "Q": 75854564500890876483496500384409231901855133430864952677676421721580214262558250045833452600117995640028651480578316408566751206202130636971969321734249034279687547171790042892542679167026946573968535448039699119565503454817512047879316013647601437778895162289420329460536420861020720557051409157484742053769 + }, + { + "PaillierSK": { + "N": 26723870799992085108869546978153583903369706088168083742244159090735484100208146492121615286184432514205245421757050777132600249949760335204760440730426160499364110451759957490921645520416721530671311214599458837511388928097547178394601502526807946677793504886911880098281711166642344716425177840605403468027738669850438692375217909468158239813685976612027547845797546922879586543279806133533414016574796969254441081617638273385383896185880814653525907620162194945920224483563467627618890567067194348363928270334512550200498125057498503783857569650615091082302587171567195208060686741397242999151175419270358765662217, + "LambdaN": 13361935399996042554434773489076791951684853044084041871122079545367742050104073246060807643092216257102622710878525388566300124974880167602380220365213080249682055225879978745460822760208360765335655607299729418755694464048773589197300751263403973338896752443455940049140855583321172358212588920302701734013705474553708807150136226955375830741784632529113506702654232057724314933072084413448458350009716279537919279769232319855570869167817895891596129867792773486264091695835351635080989996098592438174094441850340120097267749483028011115694256775616330066545522210354352199451257161339503905057976527678038557352098, + "PhiN": 26723870799992085108869546978153583903369706088168083742244159090735484100208146492121615286184432514205245421757050777132600249949760335204760440730426160499364110451759957490921645520416721530671311214599458837511388928097547178394601502526807946677793504886911880098281711166642344716425177840605403468027410949107417614300272453910751661483569265058227013405308464115448629866144168826896916700019432559075838559538464639711141738335635791783192259735585546972528183391670703270161979992197184876348188883700680240194535498966056022231388513551232660133091044420708704398902514322679007810115953055356077114704196, + "P": 175100947633664948331242692945251377313511570661714439919748314241963328778125126076966805024435307337357532579683501364813737746463784902767773779423750641597386390008653689590901379678925761747720342351110129988568100780015819990211184970470055575667761657889758786820491815367565513564626268882784901142363, + "Q": 152619795387413126614212864461326952803199983138820000569334493188993348357512180559530511530929102841244989499490132309428420103781237967565874105152897331794654701884110667866009195191083710268019044282722180017394525311426661562257871128912375373543781092968732022337680603350669675470596095031496749815659 + }, + "NTildei": 28624624686932925957150681042929273756809396218326966135018950205838122251463678085402315398088261514258856369014648390578521215309078104097698418324220723299847605507652052055911798238666904997894656234380282614314618649665242142143552491273511194294759533043630690352614458759187755219413112817424308342962950527695017372689367751993696671537428244670316113927800794610524703450820767269914203908662968962804978361864311083065787611295194701569030867188282226742716054326634008224697413720522051224244583013312474610776871930848283804012981928346198764711995247404132952144926252993418758071365354926653002833164209, + "H1i": 14026530141610668143856820420407656458432764374680020340571355631267210064006968072799105476032725089332039260073849275232014656789736661391193504152100732745094483418964125973918903900336895808960186954958138038426859748265459715997561763338475911201695863946142914553100703987724399497173060195922367447476997829115857087178783879201403579924033786649966962715477478264141714261448279095640953046222441971357858519897068717161539179362097372991276894926858571668032687275950623711928425165272738042543648866916378553081373750092641340783454021964459927757376327530918382782737461814621557767837977603932385255335438, + "H2i": 19283799849145394129320625350432713426475520862461400544155708240711309285561900932614928510337804121412965541890849867199640968887504032199042841733812607614755196200526682565756047755562312740623800760856499926583273826179391304381102328756953959130136385902351066167547535192380497694912835168622129179025476563060557206669766472640525587783151341927408624850912254165146029128771342027356650114359875501951630394635187190203263624041937663862426088837501407972579151686169107300498907506758915191333955480218680703336594433601740584371334487880159857068388403068198491336659162154463620222655416430696186215208178, + "Alpha": 5749843232223250574850558859986300041942204669388550286914769306149925653176196026966378499575714834222249624589331601858347797630909562813946721630811370402107387056922488419175647162616595418741646966864878906471955454249886174549430589585293438801360784160237347119540713862706724295853522854421579522800213721297410639723831508165742795445446556797408522127106494886716485331369696390778359617445809582186515978139306075539060603968273888878373614402427413436785066126420107550592965029648130662941620454409579881014399966348172506501799820496989990227126729160499430069315918989279002409454093802288365491119166, + "Beta": 6753796314668828023626742400192339961053247805158968448791189278405219197009230669389398530419912244722385870020796555412561987878937184217488142664309567853974200613130037797655518344070788332814595862356099067820866002844120560074558472034802025771882721224256726289456093794408406800753595989915246900363486470732898874260680872010366555517719317138304938242645614190384845050878484987925715606630250172662533272249966249432135841143176301888260172433813397261471898576338720490590315697735970189528646803089703806905174325157005520878377291785478721769671160590785110558563084563103554994265281629148478652360626, + "P": 88614852581497878151639851927541736529406344746355807023626732085240385765260309797888389804578884041830053182988789251980628438677388015503251231638214169890754770188429030291098618190712362073204249318855083659015028991496118650155743033232324736954298607449121278761444607904349233916727451883796343236401, + "Q": 80755719422450223090410337056249297573741310324854412676580299097971970609746616415696786961074202704926836995119764697750125109322932545719762755190777768760956378432466025018305400229445267545918499391237141624421234190789960881879608108546903728672110028397881465289820535627855539819569714072120573944301 + }, + { + "PaillierSK": { + "N": 26031871908125071401598913810935075639993122314702909223352387013254756850476217922269138225633646118710113525677829829960378250317168364628938674751357403423389801750904028738122150174417786786246791232420614321411287181275287316177615899664334577860429869495881683427458389699589380827444427594814760879588414915824416225999375189611722231623865011980429668268364999466051413587719374104686006165191148064512549746011863839563053925004413360911815280620599852256762900911150000345632275417193223651302865827070489670111089365401438823599873499095829996921942409718398923898306482789794736215298857716549836555989913, + "LambdaN": 13015935954062535700799456905467537819996561157351454611676193506627378425238108961134569112816823059355056762838914914980189125158584182314469337375678701711694900875452014369061075087208893393123395616210307160705643590637643658088807949832167288930214934747940841713729194849794690413722213797407380439794045566502867203995004037539785914716058756293820978784482496963546603747400145538434837572478591702286896298848557523071670800129060594094577831459038977033630391408442182918645302825164830685671226533422534755569497336621242657758730740671528514851479288464054379855616380445539909503270816671597988590989594, + "PhiN": 26031871908125071401598913810935075639993122314702909223352387013254756850476217922269138225633646118710113525677829829960378250317168364628938674751357403423389801750904028738122150174417786786246791232420614321411287181275287316177615899664334577860429869495881683427458389699589380827444427594814760879588091133005734407990008075079571829432117512587641957568964993927093207494800291076869675144957183404573792597697115046143341600258121188189155662918077954067260782816884365837290605650329661371342453066845069511138994673242485315517461481343057029702958576928108759711232760891079819006541633343195977181979188, + "P": 175193909491658409303441593996772331535333119087776217371039869663916579317191254110238201727602714098220221701404960629378784339440152844135984492488779188766893745308871440662125490556181782723481189132778325273472869310884471447660840732359915671523955590789822708843147906114127155048867316390174958534047, + "Q": 148588909190159600063672938153629860212166273699934482028965669294289513601891773706092818506361945840536926613343832790333540406852019878523633210033119000735224348956763067679544276307380497236931571092641833698621822848069036634751177020413051547459877199500341478230573992600790053708357056963684415476679 + }, + "NTildei": 29222158298155166695104931116299663569618664340728181773291467527591647292530273599837988427680089318168606469472880438852377560501028149937247580344563410102431529259509092211760857594934518812570949359176291554878925494195884545556694087575141351315368061600345950624347203205726805958587765395254840485607078449641835964821911353876567995038822236826436962271966340946461634035458740774858773419413455827530914858630717042374682817672046888540678530127753422371452644205088652330886737883942897332269542410300063340399452234374194502581172625744279585001277931557331804530241670315030238599435963356201072962156397, + "H1i": 330156415982565933027835973031402729449144812191428443161662192775434549908320527653614414300406041910737508644580222037134018847562136441606694057055661181109818079979311818774462193567531548078145955370090126229467798369284932781829152514373818985604751985752868313338748537039054113649045949619130272325727395658223111618681077583366422166733895629316440353631626308960917331548141842027074422722329247143664566090979920518467678017367651549718642006589732631357480488434477693504802314822108194348702444274293021973608504804124921430548183510385020028268768762905729647397798926600373975723792889415740814815047, + "H2i": 27407765995132388244657245696058842846465193613457489284080482268486686104561134939801003931949032949349693182031391996333954213993218373542518382621254706107358653562210674932655912397308223379879112209727096882491911718896134149782331390925516614741126388861654988741672110934335383394496013728482141458602740141407647241643946788202856437366438560178498493114705142609086805067510627447487746258780905892696786452619355102147293953940712069430051018401154466121711835154545618945252550009441593572452925091473697461656259197131183592837826794983800860380045031251238135934530497833914618842990437859869257192176021, + "Alpha": 8068703561045319338791816950135168271972282970417266114695781856026881349554751073620653609035741856668532877061780357941744224758942321018927524612511142941437615836787051500525059577663406161360691241043336128354340487680383425224760004367593022146314483044911756070499138562614483091857328371555422197670154469834386533594930297354597266368770821905394957405974363652387811953709857735678340195202334066915533464282746273474089083488517056425887755155850273112055767791569124454947800493677986970774563730647378380838204251433756155671722124661603753349169027630588573814795388735180612903167736882665792282027290, + "Beta": 3876473524223166595531434262908652981848550689117549535352822730295873527234419005367441280370944018085254857857146880132845179840751534603865359131569480133206417603294180461089111640881598712416328401239754643080501362221175499928930456768827702486447657750769588136740980575221130311286023262994112472080013178032408734731204598247998816398153141077192215917271963983206580216931080496594172278907156103339941014926261799513693004154717901423488370204686970158515566962370124789257214738112232819848340411307884191508950466727915323399234486824106365600930575170269338604677602056045649311053946128454963516166295, + "P": 85938832369741157120248968985971252483197739348285427991312924646208959859247514072241823171674958588421856970294017064555055021658433369678725136794927514249178278577091017403091399071011587837077616424408208774119082431130707434446365575784617895405575087152686547951651267594622353882191307793278148417669, + "Q": 85008597081091521279279601152117768515348019100337500136270928443094263907602241674324161888026609784810244767584333071909152596505153345404962613015958016969817584862506612063866664619252142344848813396485808466529767920065501945500364065938090706906012499635977077348093727117606776179328595281841063836211 + }, + { + "PaillierSK": { + "N": 26661616974222403359414724893859447643756557363346107145486809731184335627451501798120080086145787176627241224918066258044217471711997343867221990736146313313811314986971880028213031329891734757490529177891431337993307452684715254637027899818137617298154454328457812867646831974889744384042853838798700705793154070216628668751125286673961493037131949739024938908734089906357464861596821906243728729043875921287933895702418824027327331512497782181841843772668327150392233584918678025672404993278685654111687621551222648497781202031677301491040407149094472663523938181775045485674768873433005036746455424340767681133229, + "LambdaN": 13330808487111201679707362446929723821878278681673053572743404865592167813725750899060040043072893588313620612459033129022108735855998671933610995368073156656905657493485940014106515664945867378745264588945715668996653726342357627318513949909068808649077227164228906433823415987444872192021426919399350352896413334249723881600151417035375336671411497492483959164846859972859601443532060856725699957266443131509670167166226041809296996872390306503454927780645704632050736339055782287442955961439332302845153091459535115182876960631053492122048218683041784467611006347589134242358214621901048098413591515192423898257438, + "PhiN": 26661616974222403359414724893859447643756557363346107145486809731184335627451501798120080086145787176627241224918066258044217471711997343867221990736146313313811314986971880028213031329891734757490529177891431337993307452684715254637027899818137617298154454328457812867646831974889744384042853838798700705792826668499447763200302834070750673342822994984967918329693719945719202887064121713451399914532886263019340334332452083618593993744780613006909855561291409264101472678111564574885911922878664605690306182919070230365753921262106984244096437366083568935222012695178268484716429243802096196827183030384847796514876, + "P": 175377935666031786755660570177211436450380111907611958037824868372895755509356252779760511489824181767399092658930676404880297069685444401249659213519651777465351356257624143662039269347674022417059295938632797238737576256262492619014634593116323639243190104488935809108686384751566685806660124938811242086967, + "Q": 152023781514873764066792033033608257858574642149408621002545092265366219023343940012568303021165476501194468711036064003853040698031724773682328997857266108825409550549489307124453801052347026004322142693519620893289704513307824627929335189894580089058735382107841191849653244879342154112612269017108642531387 + }, + "NTildei": 21023415161514931930008466878652650089412402528643509910628555131344775794158903058369163761811104680637408260775817406933055101010078991353396708217239037610233406117989518964013955011431080536807756409589947737202805118447588754169619286059698346051434091526828610571256569564316417206639754298477685122805196892545615440112815631041008856187402317846173311204065893967539845566294007612545439663167301168890866914939671778637205312132294532685315455932227400848361283874655576282211589317437552929837915998820178547855772090057657134811218804757425834628549242669619312730165527727457922474374280635157012741361209, + "H1i": 15979859313395924571136148658272103938372277132678070185656328850555896690427265186126096171639291520357543524640425266307151982122049738808878264598206966080587709927906640387690608389668186869839953216402923927311693256889408989039177076903229553524022584907025308354010118759972205358791799330465993061080674460161824303321464792470295872129368382651158459686051383364336871730382257897383932053325036660618259973470074406164509122280382806650979917102193169315068112754326032498816760991618157715715214277113518569408529477400645370240927498578586798012381303913527260707011044009693067387622301641474678395137329, + "H2i": 3400219648626288789150267120389048671267876921097003637711074790973923585477139459215094640694084818158709978728077773527739904169606855197009342752699579884503899304360366963897162013108287406627863971362707752177726116720656411659548257360888026075554702014751238507746228702218843730081158778530747745587464924323563571971913669234138584348692135379073299032519767567815652599967281170018766276696019988439613999125787928364730268505921162016602516668092456347174784869553284192504853105190328240700628108541064081470312014006840605805807285843833534147866212446550895330114210814547493004700634134045261243609420, + "Alpha": 10968084746086553879555246005424151631351945362314644680429246279594619086481795490547770180177027337113479028220389082798572900071861443392448200276763503520560570427376023664716261778346234793033318073939745692127585713547475721641639705909319359058355835178573077774609782274457065790510114936006768976361662915708121382170755739592153979184713454213787772401345289335766812572968205368892968051801976644842791896044727706004497595735228077972228818633364818209488350957555438529541613073805942105414887874265488894469092510691335607804596893430423973847218866728459062319877402779773676930256597033350909593897945, + "Beta": 4275986465085912602037038190327168359940626612036952399077678882598121317075561451133118801920701359393828994187712811017932749085062721547706635260968141883926771954712872992294573300108782888432896766100565617540374111063873481445338754244281379709596250455026711325789081804317786986068893800559050584535395810581825654350383867621090683723404403296575545798254452059294793925405326587070269270774744714221418658615411917205850494208011064950146030237929039855940802955292868768908855211222004231747079914517136844476197364466479511494871033079340153339044310059993514529956706020475493216780800917573130241435107, + "P": 69476258668741688038577594919664335876905956586938543487896755788206168993897374629866752957331374026733148356008828420692573092081939761440587391514133910645127582786313219772844461665579743048731026561147450839535618160932594992418611075327388853616167168821845022924459985596452501813437755246921203218733, + "Q": 75649637604095871594471693631437284044569282038823214786757005709098971966306634567539461475248702621561583542981284049560600135882386712911786807118538860634013836828376264489830737293835498161381910332709274417066550695521467864502293556051033378667320092896496144727480670018979493247240881289654452764413 + }, + { + "PaillierSK": { + "N": 24052481522962876052360953346019440610188773160602387025048492823110532262773949490277423529395071335547527231561218901912183314499581635091149893746299506690057079443311927011121873860618042943963696483289967501741406838739673986526527440412352894606624268387963632920657975946786052527718342817803500056981867295297565008730358546052203974805316883404812822240385668096575271128598233183884330769588801518223928499989130081194410782399103427613109533112972374254439787046430963112599914990562447714115880755505990672481181189129691386186575437803399078059410905030250809446251354774414307498622695985998962151777661, + "LambdaN": 12026240761481438026180476673009720305094386580301193512524246411555266131386974745138711764697535667773763615780609450956091657249790817545574946873149753345028539721655963505560936930309021471981848241644983750870703419369836993263263720206176447303312134193981816460328987973393026263859171408901750028490778079419704517561722204670476010700428348702936799250029063085482068058802362283770023080631467066196295454957049844258347417091208189681961690693100734894148208732084181959095352415846890629309643658661929229804843619696068112637043032894208588825519259562494733181881254395863290773220136287817659733196526, + "PhiN": 24052481522962876052360953346019440610188773160602387025048492823110532262773949490277423529395071335547527231561218901912183314499581635091149893746299506690057079443311927011121873860618042943963696483289967501741406838739673986526527440412352894606624268387963632920657975946786052527718342817803500056981556158839409035123444409340952021400856697405873598500058126170964136117604724567540046161262934132392590909914099688516694834182416379363923381386201469788296417464168363918190704831693781258619287317323858459609687239392136225274086065788417177651038519124989466363762508791726581546440272575635319466393052, + "P": 143361985778015155255717551936923351473978017172304289042514220757059700028335455085828576502862530627104624322282919374840443445734819842795534922000993904620908353983877764688477404256971873407059086532102626198017920248257036511630382965980596012545444437988112039123267439451156170390211842842795458644363, + "Q": 167774472377958451658419159315030052986207981766919451285027704854075310965173161258456031823004855204232965752747473302875504770952228406390616804769910561522461228278721429720732754611694582089534351650029586673476029489298124400858989049001304395826941467273231043365578543236569781792211567520847226740247 + }, + "NTildei": 28495126655757486667458758522417879908145225138354011756695010310230080843775810691475508475189296932048204405538269234421309761999801641929339698921549089123747487722383263763650748100682062308320985638751456070929390702185959886711286692830051395068835285369347464130652877447989491271831963284492875520804370323467682501001588488044404416399192709674700712048722419143089138256847841944162078218754909772083880798045725064834323189904527799781096814998522360671548233319610818087987495141065235350701796581438153247939692152277023749182901393787894844691359824946779571324097127401565736630547441431638107656293181, + "H1i": 28139204291736107581049547396165574863203234868282840343850475611316742281564952788511685665677202050956468636410612105292574914465434643437843536369499800973537255887468353922417457678554017111438981470025595971749690307187278367116499631220803915226465968187669153053419544887620086914071454919928871241158300708745494285279416823564052160722164817586912567257185619724260285349040459813098794960371406943099932478046860993247998640963947483501215188172267462681319793590454634110086853775351617557697057810522572588207414329609572696435247631910943969381789031696553152361619843583633492290532183651674932213793892, + "H2i": 18343012511728251152619273706563580107510983295836399283735757723908485525490953893654379011407161304401117417774076488232861803078647038728469577888266739586943256069684503651055461129018569812210376305552773590891152511820448669598841281506429101111309136225768510573139029468583102907541234250967601742438791471921912179677553585666437013724159880990846845788805031792541045321076580789423919030557731118498588308112703684225304436096670649567207199927694259713849005362656595679403797591514253615426557419641322457053452553097223033051279368579757091249705121495314693330896281903365995694137463060183428898198895, + "Alpha": 15330324895839015629749164127055887108944620243211969987449311969454718352088715974341715252084527967431448134646088538144420853512995416273561618732151484903387355022214943735562071551195740107272138532892172113447845492301731674107910459116712851894480660771113461325203036787434742017215150159527872851126730784650009572323695990492300938571809441720444844601347874407418810527702088091020403934561398373419763402833712691730366310455834664292087593557723172758408828284194227131181575666576412848989757601500842237719690269216451865612174339505104169377221217624930504464413569272829312165764535900058466357572390, + "Beta": 1584804323870892662282706835809123240745461685457525841169702095713608517862442308385821550763247054160223993296163879255563530547139352807199871660462636080555894933373242237257723943484371130735538117066453264871610226674566607357030611411397696127526175338557535242927809949940694042389710283972054610301710349844906988403489741042387287668480277606438943930436243402434875142851991181176503058870337350050444131908536152285827112289950892735617965743934215843566437456037014148930468520915817894258024507411544349768951685233872346797375358616829119999319099828312162597921883543028221158582453429488858083709857, + "P": 84950601201178680727694881016637427640675160632220282849163482823997997624811703349976210542139670000850013753141650724543288468187042649202717339153218135793741655889877785431096531556507754254442924898238183920841803363232817140180008085098652654853071998322801343026310321567988075383000517691452076606659, + "Q": 83857931117743872301069013225213543854875205565418243931239291845157017247103778701694700849014042740796258819941830440731676813621100540961221084761025112092067689163962852285080221440034517787418977393812057026030822736805440919832827043894694378993424330632939046396206297815473996517457979684443043156749 + }, + { + "PaillierSK": { + "N": 28532083390186780519280501648721793129467844011498892536321043231855805410525503292096724543106431760326881112668992270200631197658215906941153806681817268863741858185487459659769348325078369392105144502823812902999129783542213853693259844069370505695481980103201086263132087207888270781551594469104238264488722908308751351423812207730579513284516868030187797994774171885991073257793492834857578371655897507676075586723447601741640197909930741428153757604093402647706619676570312196526983651713282712968671768369679862403878137205778316574735693551319153062000460655429895155942504997817787890847396211076822901784581, + "LambdaN": 14266041695093390259640250824360896564733922005749446268160521615927902705262751646048362271553215880163440556334496135100315598829107953470576903340908634431870929092743729829884674162539184696052572251411906451499564891771106926846629922034685252847740990051600543131566043603944135390775797234552119132244192287698227136022313780702650016000992398925068563143220558970429168692627477543116924614551673124866260635793794207570681174997235568732218257150735724569275482004567571417817282327186182657848329645786567178961556214732909321449820592389214182098253555346219400630541016873385239191498208412926667707247526, + "PhiN": 28532083390186780519280501648721793129467844011498892536321043231855805410525503292096724543106431760326881112668992270200631197658215906941153806681817268863741858185487459659769348325078369392105144502823812902999129783542213853693259844069370505695481980103201086263132087207888270781551594469104238264488384575396454272044627561405300032001984797850137126286441117940858337385254955086233849229103346249732521271587588415141362349994471137464436514301471449138550964009135142835634564654372365315696659291573134357923112429465818642899641184778428364196507110692438801261082033746770478382996416825853335414495052, + "P": 178397192612604798526968290931294714501451132274433804082417650074685738489897228727793893982225225752546520687942691828749089572044809494101838651319357498350212052895901283392803214993660904200357018761843124999768174912124384047979406690868733945683187341307267400295206865581696902698498782880780293418027, + "Q": 159935719684474580657678034348186568030619047776237904250636295058050134048640519895935248570326032191007794447916494771528758343414794469615404651302596010805443614539268077499615782347256493071655458034702379480997532827835289627115102082022054919810162621683826494565264385465612605152480602342707193871503 + }, + "NTildei": 26733289920026365778492885647254460326189033900698045325878057693985834595606177527651925592751912533688289358811198236988558779803498932755962261335119977382879838118872049616532997223764282759238906274176746425781577330531540107005260467055435414330514150021447276532181975314736550975239920227482389984722322579308534711831900966819220456144137887514935479109302466481476623097815121673104249856435477007435919192956671578798369291760464153531184470673674358246537004490313923351679993019195792761859368211433162663418187477894690176237777206320829181657018815385414525999759892853853566230626251256122415379372273, + "H1i": 20200543952388709836743372877597237406943839896347747383212226636682579390266700597516989020052810659597285482842863107076855223507089169031625149501738327365377781000351094672136173619680418109058858410399178590854493961183919089388663926099027471020358277104027668430773796084643496915015366640313310406276341135477922566455007610964540575699183201893462143061658856152480416538043586984610654740317757780453423860977037150598661267662470571960792850872798222793180041549984494604484570404209309244734823616789953164633842532577002860321511616983711280573990669660555250087063103648291591101220045659028218328100956, + "H2i": 10011436944148999704464729478673561825330402052836383319764735936166653136794101837350208534508492332341341255965887981883803557324617591767191078500745728335718952176480235872384811844719845355637797106611028176253832039374252087544755039245396420549730559767508655771782302883449821573989466800538465631076744692643173821046022994406780555158980770756763482451242912479953939932777447178637115678143977047057716538247771280467984161676537129369878726903024915919667830804872470049046316943500229610935124696240719749606229887055456619311751010965234390942106512645535387078751015648502532133358344733101213575772732, + "Alpha": 15565436498311155112588249022821862520831375916928397435754535386877538566831991068953160110964367946591299485137968199245528685773874438629821319030568442020250031560538582849448617250539719821910279322962449191452271999059043350678608792762537434805626510336661264707694517631088713862394614612816487271259264251433918921035494541091761245802760144441019786785426300945977040679290824987341086329162816295495152796652752825841845446501173445259521050149562516359758631274842233544201310219913069987127893273202943549304158659063779323230282264917107397543995383601760295260172143331759309750377027464738611257734556, + "Beta": 3883940474746516653806520604722516014415511103852633009581932326244372262855908107481901854763864126060702763451703384991981727435141718894619578305082311541038582671470968661787464939754228927702599076508120205169006314991280457956565876710934694218356058640551897261055991046770978180843036445234185579582345903284236515859517484716034054747281057931255577073243118208370448587951507091942552174494547468025928158407723447011390748139792263947401625790925853148867805209194434938388139467180472257196036659617838392275430990913650256930599038015752735092722456977368748464845214179352136934855551311384685460244367, + "P": 88168130008404525570080700707103177440944367692305190140628151484436185265313682857334978033182046126756391709077961850645380317710759458144830875967861656144788225571162087620278111559981354160418480933560535964383989980107742493600211919122200727043573677532742832571945019097078697284347853182975980385653, + "Q": 75802021426217289822102079905729104809367514694283311880419363873595399488548968787217821908097262719839159908360383891791627768255826891968397183231757256441595750371220484881193527416981015775805677238811550999891265011630635966369776465629277030122077586637094353538177149941931293814240150871910595472969 + }, + { + "PaillierSK": { + "N": 26996640296300651415400498554401486137947845822254251887766916948226349613131632612732250222343209672211664304457350856416313173796997278128216054444054531101181996295277761291573895534184826657300078523433362006179536527761026593314939857983859899807879337182885316022770084078937119713759957978793209959321773558388531252778985777267232264523363283291777180822279473099246650733627006953857220660330089524556812367404172433334239055657616263358739798733423460431363276818010096360055425692099023422440987119348965576326344453013140311995841156056046100731017938538439336584387442062457183076226558611796036832603917, + "LambdaN": 13498320148150325707700249277200743068973922911127125943883458474113174806565816306366125111171604836105832152228675428208156586898498639064108027222027265550590998147638880645786947767092413328650039261716681003089768263880513296657469928991929949903939668591442658011385042039468559856879978989396604979660722342895912497036521394673614697081030521511819274404285369261080473923995316551810539734496685124647636628742007298357742572095392117349769020737898095493776613311158059341001587427820508436790485543414473817465102062746820886491367913498519251718054955493855959951603808229326323526028511694853429746146238, + "PhiN": 26996640296300651415400498554401486137947845822254251887766916948226349613131632612732250222343209672211664304457350856416313173796997278128216054444054531101181996295277761291573895534184826657300078523433362006179536527761026593314939857983859899807879337182885316022770084078937119713759957978793209959321444685791824994073042789347229394162061043023638548808570738522160947847990633103621079468993370249295273257484014596715485144190784234699538041475796190987553226622316118682003174855641016873580971086828947634930204125493641772982735826997038503436109910987711919903207616458652647052057023389706859492292476, + "P": 157905148394759100940661864300050564272121208960007256882238286839980193380764286575055981798858297695053183016801509876409424866294884395357392006776721650508036186041981370664938186323116873237278846002699640274839145482649991664889544965563098882935710106691573689155912402662654496699699038906112143322839, + "Q": 170967448311499605002326055702819797030119059178624756826496290245722692255609563661085209537860977566485926903356326742344486600537144263844365250850547793302014009651996307387312650134889675622737186517318301121301182036848547348215784093444498411972317444035842992023913201141881527469836183183065196988603 + }, + "NTildei": 22436061566505115400255364934206443514880121947326950289482693221702208610753589741635209396952016373091555079648000236956995723851771160867556885395156505824344051167260809392148181658491568955113664358234083709771490930482313936184041101703657962234454203064371095370697130577170623689309659082800556686989285401665635869590761592643659123627663975825165592363434104158359403232225674866770531989356076225150418301435942369309478628288044705111511133055753831395876575155226508558182640100683925441038184263158472000921072850578784476359636108643340599841481197255164343314382678422505049162325472333625389562931577, + "H1i": 1199533861400575692856681402875292641734445351049563751937381586786477850751339951730561029476059139435535136420766353716253652623959385490555012010952213339410149494917020405689897932714018837946028125059091076013670791455394598890225844605686738602846173424436744756985469959258897687442804987490208370486068841656661510129964860544533440485303815470015661572402917804294333537516509746860702225007831407081975310947327910357478374447435164140164563121806197423582324070051275347417046411444337671579348228702122342464271403333762205833314842533725503951317809843463689279836236681777422863958847719655200665113697, + "H2i": 13975318898659837800412782768896011209985361726089775423824545800209227616884631073198171871883509581761333410095276918044890427119892906583746887329139403552379899531197309892138579515482522906489928976492442700099383674999002671192437729288280570458900729667558341917187130696878318333857273458025956269073592409661111143280330222888669910108452967384467607956021808171117737779006368835341901925347805963951029264904748092973628455762574918478477835335047063922027885012324366725886796945118396831977791108363699233412147104604560958899333031670818830779452001144139308962969607201086231581935024723793409846975956, + "Alpha": 7839871763817937648281508585771302168929438757070927924687782490100206714077674159655813164749073436760189220160719088320191721883374726294445050149155257503084546639744065102281188791160371649613509716336894750723421118393299089348711808142885248290365889240940587668495901911421541811175413308480394142999149048504367580084950000517351744315316986638974578499809054006704919313577480039567568168523993731975610844099512385233001358794335198157064809404551699357948747484230034228066907012460434902840508195179312607447867351440943484605479326566206818018968111409712608800887939979156700703436384338851571345319120, + "Beta": 455800020114336955047130350973908643968328619658648588284490242522854443889155886353368944844265827442470164696971726435102432811704767203050650599031223115644956163891750427472852265371320538935861137038980318883977212529964675222874366812637594065992186197548836529257983481168102743315233774248355356379282636239666047779224281459908779764056063684259221434607229600973188419803850680781307469601395038817459618625139046409207026317585277284165495620012660779577229570630797987283289009090561614707153014706263396359865315756090284423936957661245285858481179837641828947562030677390211533826134265382656454644752, + "P": 68316017966226044203323749387426902594489517305802024236273332367317700374032653511484870688184356264284841569881511332461005356624315345900612836543970100541105886547528423917928311100707782826904932690977668649249929795320653366466431337983769579326611029573726938313698391628000620296807273780702069610711, + "Q": 82103956855319849872216320654041726343405442413793796529484052448206141681339480943464447078010886607002703142238693643490834237742902859271062327382979840371867993179940812439698651194351239806544962334234075346850558367107330458640769005325621377862833899110675064788082408737470330896447881745451142755499 + } +] diff --git a/tss-lib/ecdsa/keygen/types.go b/tss-lib/ecdsa/keygen/types.go new file mode 100644 index 0000000..b1da835 --- /dev/null +++ b/tss-lib/ecdsa/keygen/types.go @@ -0,0 +1,43 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "math/big" + + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TaskName identifies the keygen protocol in error messages. +const TaskName = "ecdsa-keygen" + +const paillierBitsLen = 2048 + +type ( + localMessageStore struct { + kgRound1Messages, + kgRound2Message1s, + kgRound2Message2s, + kgRound3Messages []*tss.Message + } + + localTempData struct { + localMessageStore + + // temp data (thrown away after keygen) + ui *big.Int // used for tests + KGCs []cmt.HashCommitment + vs vss.Vs + ssid []byte + ssidNonce *big.Int + shares vss.Shares + deCommitPolyG cmt.HashDeCommitment + // [FORK] Store VSS polynomial coefficients for SNARK witness extraction. + Poly []*big.Int + } +) diff --git a/tss-lib/ecdsa/resharing/ecdsa-resharing.pb.go b/tss-lib/ecdsa/resharing/ecdsa-resharing.pb.go deleted file mode 100644 index e418b08..0000000 --- a/tss-lib/ecdsa/resharing/ecdsa-resharing.pb.go +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.0 -// protoc v3.19.4 -// source: protob/ecdsa-resharing.proto - -package resharing - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// -// The Round 1 data is broadcast to peers of the New Committee in this message. -type DGRound1Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - EcdsaPubX []byte `protobuf:"bytes,1,opt,name=ecdsa_pub_x,json=ecdsaPubX,proto3" json:"ecdsa_pub_x,omitempty"` - EcdsaPubY []byte `protobuf:"bytes,2,opt,name=ecdsa_pub_y,json=ecdsaPubY,proto3" json:"ecdsa_pub_y,omitempty"` - VCommitment []byte `protobuf:"bytes,3,opt,name=v_commitment,json=vCommitment,proto3" json:"v_commitment,omitempty"` - Ssid []byte `protobuf:"bytes,4,opt,name=ssid,proto3" json:"ssid,omitempty"` -} - -func (x *DGRound1Message) Reset() { - *x = DGRound1Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound1Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound1Message) ProtoMessage() {} - -func (x *DGRound1Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound1Message.ProtoReflect.Descriptor instead. -func (*DGRound1Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{0} -} - -func (x *DGRound1Message) GetEcdsaPubX() []byte { - if x != nil { - return x.EcdsaPubX - } - return nil -} - -func (x *DGRound1Message) GetEcdsaPubY() []byte { - if x != nil { - return x.EcdsaPubY - } - return nil -} - -func (x *DGRound1Message) GetVCommitment() []byte { - if x != nil { - return x.VCommitment - } - return nil -} - -func (x *DGRound1Message) GetSsid() []byte { - if x != nil { - return x.Ssid - } - return nil -} - -// -// The Round 2 data is broadcast to other peers of the New Committee in this message. -type DGRound2Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PaillierN []byte `protobuf:"bytes,1,opt,name=paillier_n,json=paillierN,proto3" json:"paillier_n,omitempty"` - ModProof [][]byte `protobuf:"bytes,2,rep,name=modProof,proto3" json:"modProof,omitempty"` - NTilde []byte `protobuf:"bytes,3,opt,name=n_tilde,json=nTilde,proto3" json:"n_tilde,omitempty"` - H1 []byte `protobuf:"bytes,4,opt,name=h1,proto3" json:"h1,omitempty"` - H2 []byte `protobuf:"bytes,5,opt,name=h2,proto3" json:"h2,omitempty"` - Dlnproof_1 [][]byte `protobuf:"bytes,6,rep,name=dlnproof_1,json=dlnproof1,proto3" json:"dlnproof_1,omitempty"` - Dlnproof_2 [][]byte `protobuf:"bytes,7,rep,name=dlnproof_2,json=dlnproof2,proto3" json:"dlnproof_2,omitempty"` -} - -func (x *DGRound2Message1) Reset() { - *x = DGRound2Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound2Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound2Message1) ProtoMessage() {} - -func (x *DGRound2Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound2Message1.ProtoReflect.Descriptor instead. -func (*DGRound2Message1) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{1} -} - -func (x *DGRound2Message1) GetPaillierN() []byte { - if x != nil { - return x.PaillierN - } - return nil -} - -func (x *DGRound2Message1) GetModProof() [][]byte { - if x != nil { - return x.ModProof - } - return nil -} - -func (x *DGRound2Message1) GetNTilde() []byte { - if x != nil { - return x.NTilde - } - return nil -} - -func (x *DGRound2Message1) GetH1() []byte { - if x != nil { - return x.H1 - } - return nil -} - -func (x *DGRound2Message1) GetH2() []byte { - if x != nil { - return x.H2 - } - return nil -} - -func (x *DGRound2Message1) GetDlnproof_1() [][]byte { - if x != nil { - return x.Dlnproof_1 - } - return nil -} - -func (x *DGRound2Message1) GetDlnproof_2() [][]byte { - if x != nil { - return x.Dlnproof_2 - } - return nil -} - -// -// The Round 2 "ACK" is broadcast to peers of the Old Committee in this message. -type DGRound2Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DGRound2Message2) Reset() { - *x = DGRound2Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound2Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound2Message2) ProtoMessage() {} - -func (x *DGRound2Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound2Message2.ProtoReflect.Descriptor instead. -func (*DGRound2Message2) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{2} -} - -// -// The Round 3 data is sent to peers of the New Committee in this message. -type DGRound3Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Share []byte `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"` -} - -func (x *DGRound3Message1) Reset() { - *x = DGRound3Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound3Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound3Message1) ProtoMessage() {} - -func (x *DGRound3Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound3Message1.ProtoReflect.Descriptor instead. -func (*DGRound3Message1) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{3} -} - -func (x *DGRound3Message1) GetShare() []byte { - if x != nil { - return x.Share - } - return nil -} - -// -// The Round 3 data is broadcast to peers of the New Committee in this message. -type DGRound3Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - VDecommitment [][]byte `protobuf:"bytes,1,rep,name=v_decommitment,json=vDecommitment,proto3" json:"v_decommitment,omitempty"` -} - -func (x *DGRound3Message2) Reset() { - *x = DGRound3Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound3Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound3Message2) ProtoMessage() {} - -func (x *DGRound3Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound3Message2.ProtoReflect.Descriptor instead. -func (*DGRound3Message2) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{4} -} - -func (x *DGRound3Message2) GetVDecommitment() [][]byte { - if x != nil { - return x.VDecommitment - } - return nil -} - -// -// The Round 4 "ACK" is broadcast to peers of the Old and New Committees from the New Committee in this message. -type DGRound4Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DGRound4Message2) Reset() { - *x = DGRound4Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound4Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound4Message2) ProtoMessage() {} - -func (x *DGRound4Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound4Message2.ProtoReflect.Descriptor instead. -func (*DGRound4Message2) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{5} -} - -// -// The Round 4 message to peers of New Committees from the New Committee in this message. -type DGRound4Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - FacProof [][]byte `protobuf:"bytes,1,rep,name=facProof,proto3" json:"facProof,omitempty"` -} - -func (x *DGRound4Message1) Reset() { - *x = DGRound4Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound4Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound4Message1) ProtoMessage() {} - -func (x *DGRound4Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_resharing_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound4Message1.ProtoReflect.Descriptor instead. -func (*DGRound4Message1) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_resharing_proto_rawDescGZIP(), []int{6} -} - -func (x *DGRound4Message1) GetFacProof() [][]byte { - if x != nil { - return x.FacProof - } - return nil -} - -var File_protob_ecdsa_resharing_proto protoreflect.FileDescriptor - -var file_protob_ecdsa_resharing_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x72, - 0x65, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, - 0x62, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x65, - 0x63, 0x64, 0x73, 0x61, 0x2e, 0x72, 0x65, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x88, - 0x01, 0x0a, 0x0f, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x65, 0x63, 0x64, 0x73, 0x61, 0x5f, 0x70, 0x75, 0x62, 0x5f, - 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, - 0x62, 0x58, 0x12, 0x1e, 0x0a, 0x0b, 0x65, 0x63, 0x64, 0x73, 0x61, 0x5f, 0x70, 0x75, 0x62, 0x5f, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x63, 0x64, 0x73, 0x61, 0x50, 0x75, - 0x62, 0x59, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x73, 0x69, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x73, 0x69, 0x64, 0x22, 0xc4, 0x01, 0x0a, 0x10, 0x44, 0x47, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x09, 0x70, 0x61, 0x69, 0x6c, 0x6c, 0x69, 0x65, 0x72, 0x4e, 0x12, 0x1a, 0x0a, - 0x08, 0x6d, 0x6f, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x08, 0x6d, 0x6f, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x5f, 0x74, - 0x69, 0x6c, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x54, 0x69, 0x6c, - 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, - 0x68, 0x31, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, - 0x68, 0x32, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x31, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x31, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x32, 0x18, - 0x07, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x6c, 0x6e, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x32, - 0x22, 0x12, 0x0a, 0x10, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x32, 0x22, 0x28, 0x0a, 0x10, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x22, 0x39, - 0x0a, 0x10, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x32, 0x12, 0x25, 0x0a, 0x0e, 0x76, 0x5f, 0x64, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0d, 0x76, 0x44, 0x65, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x12, 0x0a, 0x10, 0x44, 0x47, 0x52, - 0x6f, 0x75, 0x6e, 0x64, 0x34, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x22, 0x2e, 0x0a, - 0x10, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x34, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x31, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x61, 0x63, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x08, 0x66, 0x61, 0x63, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x11, 0x5a, - 0x0f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2f, 0x72, 0x65, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_protob_ecdsa_resharing_proto_rawDescOnce sync.Once - file_protob_ecdsa_resharing_proto_rawDescData = file_protob_ecdsa_resharing_proto_rawDesc -) - -func file_protob_ecdsa_resharing_proto_rawDescGZIP() []byte { - file_protob_ecdsa_resharing_proto_rawDescOnce.Do(func() { - file_protob_ecdsa_resharing_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_ecdsa_resharing_proto_rawDescData) - }) - return file_protob_ecdsa_resharing_proto_rawDescData -} - -var file_protob_ecdsa_resharing_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_protob_ecdsa_resharing_proto_goTypes = []interface{}{ - (*DGRound1Message)(nil), // 0: binance.tsslib.ecdsa.resharing.DGRound1Message - (*DGRound2Message1)(nil), // 1: binance.tsslib.ecdsa.resharing.DGRound2Message1 - (*DGRound2Message2)(nil), // 2: binance.tsslib.ecdsa.resharing.DGRound2Message2 - (*DGRound3Message1)(nil), // 3: binance.tsslib.ecdsa.resharing.DGRound3Message1 - (*DGRound3Message2)(nil), // 4: binance.tsslib.ecdsa.resharing.DGRound3Message2 - (*DGRound4Message2)(nil), // 5: binance.tsslib.ecdsa.resharing.DGRound4Message2 - (*DGRound4Message1)(nil), // 6: binance.tsslib.ecdsa.resharing.DGRound4Message1 -} -var file_protob_ecdsa_resharing_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_protob_ecdsa_resharing_proto_init() } -func file_protob_ecdsa_resharing_proto_init() { - if File_protob_ecdsa_resharing_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_ecdsa_resharing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound1Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_resharing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound2Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_resharing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound2Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_resharing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound3Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_resharing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound3Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_resharing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound4Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_resharing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound4Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_ecdsa_resharing_proto_rawDesc, - NumEnums: 0, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_ecdsa_resharing_proto_goTypes, - DependencyIndexes: file_protob_ecdsa_resharing_proto_depIdxs, - MessageInfos: file_protob_ecdsa_resharing_proto_msgTypes, - }.Build() - File_protob_ecdsa_resharing_proto = out.File - file_protob_ecdsa_resharing_proto_rawDesc = nil - file_protob_ecdsa_resharing_proto_goTypes = nil - file_protob_ecdsa_resharing_proto_depIdxs = nil -} diff --git a/tss-lib/ecdsa/resharing/local_party.go b/tss-lib/ecdsa/resharing/local_party.go deleted file mode 100644 index 24cbba5..0000000 --- a/tss-lib/ecdsa/resharing/local_party.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Implements Party -// Implements Stringer -var _ tss.Party = (*LocalParty)(nil) -var _ fmt.Stringer = (*LocalParty)(nil) - -type ( - LocalParty struct { - *tss.BaseParty - params *tss.ReSharingParameters - - temp localTempData - input, save keygen.LocalPartySaveData - - // outbound messaging - out chan<- tss.Message - end chan<- *keygen.LocalPartySaveData - } - - localMessageStore struct { - dgRound1Messages, - dgRound2Message1s, - dgRound2Message2s, - dgRound3Message1s, - dgRound3Message2s, - dgRound4Message1s, - dgRound4Message2s []tss.ParsedMessage - } - - localTempData struct { - localMessageStore - - // temp data (thrown away after rounds) - NewVs vss.Vs - NewShares vss.Shares - VD cmt.HashDeCommitment - - // temporary storage of data that is persisted by the new party in round 5 if all "ACK" messages are received - newXi *big.Int - newKs []*big.Int - newBigXjs []*crypto.ECPoint // Xj to save in round 5 - - ssid []byte - ssidNonce *big.Int - } -) - -// Exported, used in `tss` client -// The `key` is read from and/or written to depending on whether this party is part of the old or the new committee. -// You may optionally generate and set the LocalPreParams if you would like to use pre-generated safe primes and Paillier secret. -// (This is similar to providing the `optionalPreParams` to `keygen.LocalParty`). -func NewLocalParty( - params *tss.ReSharingParameters, - key keygen.LocalPartySaveData, - out chan<- tss.Message, - end chan<- *keygen.LocalPartySaveData, -) tss.Party { - oldPartyCount := len(params.OldParties().IDs()) - subset := key - if params.IsOldCommittee() { - subset = keygen.BuildLocalSaveDataSubset(key, params.OldParties().IDs()) - } - p := &LocalParty{ - BaseParty: new(tss.BaseParty), - params: params, - temp: localTempData{}, - input: subset, - save: keygen.NewLocalPartySaveData(params.NewPartyCount()), - out: out, - end: end, - } - // msgs init - p.temp.dgRound1Messages = make([]tss.ParsedMessage, oldPartyCount) // from t+1 of Old Committee - p.temp.dgRound2Message1s = make([]tss.ParsedMessage, params.NewPartyCount()) // from n of New Committee - p.temp.dgRound2Message2s = make([]tss.ParsedMessage, params.NewPartyCount()) // " - p.temp.dgRound3Message1s = make([]tss.ParsedMessage, oldPartyCount) // from t+1 of Old Committee - p.temp.dgRound3Message2s = make([]tss.ParsedMessage, oldPartyCount) // " - p.temp.dgRound4Message1s = make([]tss.ParsedMessage, params.NewPartyCount()) // from n of New Committee - p.temp.dgRound4Message2s = make([]tss.ParsedMessage, params.NewPartyCount()) // from n of New Committee - // save data init - if key.LocalPreParams.ValidateWithProof() { - p.save.LocalPreParams = key.LocalPreParams - } - return p -} - -func (p *LocalParty) FirstRound() tss.Round { - return newRound1(p.params, &p.input, &p.save, &p.temp, p.out, p.end) -} - -func (p *LocalParty) Start() *tss.Error { - return tss.BaseStart(p, TaskName) -} - -func (p *LocalParty) Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) { - return tss.BaseUpdate(p, msg, TaskName) -} - -func (p *LocalParty) UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (bool, *tss.Error) { - msg, err := tss.ParseWireMessage(wireBytes, from, isBroadcast) - if err != nil { - return false, p.WrapError(err) - } - return p.Update(msg) -} - -func (p *LocalParty) ValidateMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - if ok, err := p.BaseParty.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - // check that the message's "from index" will fit into the array - var maxFromIdx int - switch msg.Content().(type) { - case *DGRound2Message1, *DGRound2Message2, *DGRound4Message1, *DGRound4Message2: - maxFromIdx = len(p.params.NewParties().IDs()) - 1 - default: - maxFromIdx = len(p.params.OldParties().IDs()) - 1 - } - if maxFromIdx < msg.GetFrom().Index { - return false, p.WrapError(fmt.Errorf("received msg with a sender index too great (%d <= %d)", - maxFromIdx, msg.GetFrom().Index), msg.GetFrom()) - } - return true, nil -} - -func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - // ValidateBasic is cheap; double-check the message here in case the public StoreMessage was called externally - if ok, err := p.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - fromPIdx := msg.GetFrom().Index - - // switch/case is necessary to store any messages beyond current round - // this does not handle message replays. we expect the caller to apply replay and spoofing protection. - switch msg.Content().(type) { - case *DGRound1Message: - p.temp.dgRound1Messages[fromPIdx] = msg - case *DGRound2Message1: - p.temp.dgRound2Message1s[fromPIdx] = msg - case *DGRound2Message2: - p.temp.dgRound2Message2s[fromPIdx] = msg - case *DGRound3Message1: - p.temp.dgRound3Message1s[fromPIdx] = msg - case *DGRound3Message2: - p.temp.dgRound3Message2s[fromPIdx] = msg - case *DGRound4Message1: - p.temp.dgRound4Message1s[fromPIdx] = msg - case *DGRound4Message2: - p.temp.dgRound4Message2s[fromPIdx] = msg - default: // unrecognised message, just ignore! - common.Logger.Warningf("unrecognised message ignored: %v", msg) - return false, nil - } - return true, nil -} - -func (p *LocalParty) PartyID() *tss.PartyID { - return p.params.PartyID() -} - -func (p *LocalParty) String() string { - return fmt.Sprintf("id: %s, %s", p.PartyID(), p.BaseParty.String()) -} diff --git a/tss-lib/ecdsa/resharing/local_party_test.go b/tss-lib/ecdsa/resharing/local_party_test.go deleted file mode 100644 index 1f3681e..0000000 --- a/tss-lib/ecdsa/resharing/local_party_test.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing_test - -import ( - "crypto/ecdsa" - "fmt" - "math/big" - "runtime" - "sync/atomic" - "testing" - - "github.com/ipfs/go-log" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - . "github.com/hemilabs/x/tss-lib/v2/ecdsa/resharing" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/signing" - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - testParticipants = test.TestParticipants - testThreshold = test.TestThreshold -) - -func setUp(level string) { - if err := log.SetLogLevel("tss-lib", level); err != nil { - panic(err) - } -} - -func TestE2EConcurrent(t *testing.T) { - setUp("info") - - // tss.SetCurve(elliptic.P256()) - - threshold, newThreshold := testThreshold, testThreshold - - // PHASE: load keygen fixtures - firstPartyIdx, extraParties := 1, 1 // extra can be 0 to N-first - oldKeys, oldPIDs, err := keygen.LoadKeygenTestFixtures(testThreshold+1+extraParties+firstPartyIdx, firstPartyIdx) - assert.NoError(t, err, "should load keygen fixtures") - - // PHASE: resharing - oldP2PCtx := tss.NewPeerContext(oldPIDs) - // init the new parties; re-use the fixture pre-params for speed - fixtures, _, err := keygen.LoadKeygenTestFixtures(testParticipants) - if err != nil { - common.Logger.Info("No test fixtures were found, so the safe primes will be generated from scratch. This may take a while...") - } - newPIDs := tss.GenerateTestPartyIDs(testParticipants) - newP2PCtx := tss.NewPeerContext(newPIDs) - newPCount := len(newPIDs) - - oldCommittee := make([]*LocalParty, 0, len(oldPIDs)) - newCommittee := make([]*LocalParty, 0, newPCount) - bothCommitteesPax := len(oldCommittee) + len(newCommittee) - - errCh := make(chan *tss.Error, bothCommitteesPax) - outCh := make(chan tss.Message, bothCommitteesPax) - endCh := make(chan *keygen.LocalPartySaveData, bothCommitteesPax) - - updater := test.SharedPartyUpdater - - // init the old parties first - for j, pID := range oldPIDs { - params := tss.NewReSharingParameters(tss.S256(), oldP2PCtx, newP2PCtx, pID, testParticipants, threshold, newPCount, newThreshold) - P := NewLocalParty(params, oldKeys[j], outCh, endCh).(*LocalParty) // discard old key data - oldCommittee = append(oldCommittee, P) - } - // init the new parties - for j, pID := range newPIDs { - params := tss.NewReSharingParameters(tss.S256(), oldP2PCtx, newP2PCtx, pID, testParticipants, threshold, newPCount, newThreshold) - // do not use in untrusted setting - params.SetNoProofMod() - // do not use in untrusted setting - params.SetNoProofFac() - save := keygen.NewLocalPartySaveData(newPCount) - if j < len(fixtures) && len(newPIDs) <= len(fixtures) { - save.LocalPreParams = fixtures[j].LocalPreParams - } - P := NewLocalParty(params, save, outCh, endCh).(*LocalParty) - newCommittee = append(newCommittee, P) - } - - // start the new parties; they will wait for messages - for _, P := range newCommittee { - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - // start the old parties; they will send messages - for _, P := range oldCommittee { - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - newKeys := make([]keygen.LocalPartySaveData, len(newCommittee)) - endedOldCommittee := 0 - var reSharingEnded int32 - for { - fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - return - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - t.Fatal("did not expect a msg to have a nil destination during resharing") - } - if msg.IsToOldCommittee() || msg.IsToOldAndNewCommittees() { - for _, destP := range dest[:len(oldCommittee)] { - go updater(oldCommittee[destP.Index], msg, errCh) - } - } - if !msg.IsToOldCommittee() || msg.IsToOldAndNewCommittees() { - for _, destP := range dest { - go updater(newCommittee[destP.Index], msg, errCh) - } - } - - case save := <-endCh: - // old committee members that aren't receiving a share have their Xi zeroed - if save.Xi != nil { - index, err := save.OriginalIndex() - assert.NoErrorf(t, err, "should not be an error getting a party's index from save data") - newKeys[index] = *save - } else { - endedOldCommittee++ - } - atomic.AddInt32(&reSharingEnded, 1) - fmt.Println("TODO old:", len(oldCommittee), "new:", len(newCommittee), "finished:", reSharingEnded) - if atomic.LoadInt32(&reSharingEnded) == int32(len(oldCommittee)+len(newCommittee)) { - assert.Equal(t, len(oldCommittee), endedOldCommittee) - t.Logf("Resharing done. Reshared %d participants", reSharingEnded) - - // xj tests: BigXj == xj*G - for j, key := range newKeys { - // xj test: BigXj == xj*G - xj := key.Xi - gXj := crypto.ScalarBaseMult(tss.S256(), xj) - BigXj := key.BigXj[j] - assert.True(t, BigXj.Equals(gXj), "ensure BigX_j == g^x_j") - } - - // more verification of signing is implemented within local_party_test.go of keygen package - goto signing - } - } - } - -signing: - // PHASE: signing - signKeys, signPIDs := newKeys, newPIDs - signP2pCtx := tss.NewPeerContext(signPIDs) - signParties := make([]*signing.LocalParty, 0, len(signPIDs)) - - signErrCh := make(chan *tss.Error, len(signPIDs)) - signOutCh := make(chan tss.Message, len(signPIDs)) - signEndCh := make(chan *common.SignatureData, len(signPIDs)) - - for j, signPID := range signPIDs { - params := tss.NewParameters(tss.S256(), signP2pCtx, signPID, len(signPIDs), newThreshold) - P := signing.NewLocalParty(big.NewInt(42), params, signKeys[j], signOutCh, signEndCh).(*signing.LocalParty) - signParties = append(signParties, P) - go func(P *signing.LocalParty) { - if err := P.Start(); err != nil { - signErrCh <- err - } - }(P) - } - - var signEnded int32 - for { - fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) - select { - case err := <-signErrCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - return - - case msg := <-signOutCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range signParties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, signErrCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(signParties[dest[0].Index], msg, signErrCh) - } - - case signData := <-signEndCh: - atomic.AddInt32(&signEnded, 1) - if atomic.LoadInt32(&signEnded) == int32(len(signPIDs)) { - t.Logf("Signing done. Received sign data from %d participants", signEnded) - - // BEGIN ECDSA verify - pkX, pkY := signKeys[0].ECDSAPub.X(), signKeys[0].ECDSAPub.Y() - pk := ecdsa.PublicKey{ - Curve: tss.S256(), - X: pkX, - Y: pkY, - } - ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), - new(big.Int).SetBytes(signData.R), - new(big.Int).SetBytes(signData.S)) - - assert.True(t, ok, "ecdsa verify must pass") - t.Log("ECDSA signing test done.") - // END ECDSA verify - - return - } - } - } -} diff --git a/tss-lib/ecdsa/resharing/messages.go b/tss-lib/ecdsa/resharing/messages.go index 63b77ac..f2bbf32 100644 --- a/tss-lib/ecdsa/resharing/messages.go +++ b/tss-lib/ecdsa/resharing/messages.go @@ -1,292 +1,188 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package resharing import ( - "crypto/elliptic" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/facproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/modproof" - "github.com/hemilabs/x/tss-lib/v2/crypto/paillier" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -// These messages were generated from Protocol Buffers definitions into ecdsa-resharing.pb.go - -var ( - // Ensure that signing messages implement ValidateBasic - _ = []tss.MessageContent{ - (*DGRound1Message)(nil), - (*DGRound2Message1)(nil), - (*DGRound2Message2)(nil), - (*DGRound3Message1)(nil), - (*DGRound3Message2)(nil), - (*DGRound4Message1)(nil), - (*DGRound4Message2)(nil), - } -) - -// ----- // - -func NewDGRound1Message( - to []*tss.PartyID, - from *tss.PartyID, - ecdsaPub *crypto.ECPoint, - vct cmt.HashCommitment, - ssid []byte, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: to, - IsBroadcast: true, - IsToOldCommittee: false, - } - content := &DGRound1Message{ - EcdsaPubX: ecdsaPub.X().Bytes(), - EcdsaPubY: ecdsaPub.Y().Bytes(), - VCommitment: vct.Bytes(), - Ssid: ssid, - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// DGRound1Message is broadcast by old committee: ECDSA pub + VSS commitment + SSID. +type DGRound1Message struct { + ECDSAPub *crypto.ECPoint + VCommitment *big.Int + SSID []byte } +// ValidateBasic checks that required fields of DGRound1Message are non-nil. func (m *DGRound1Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.EcdsaPubX) && - common.NonEmptyBytes(m.EcdsaPubY) && - common.NonEmptyBytes(m.VCommitment) + return m != nil && m.ECDSAPub != nil && + m.VCommitment != nil && m.VCommitment.Sign() > 0 && + len(m.SSID) > 0 } -func (m *DGRound1Message) UnmarshalECDSAPub(ec elliptic.Curve) (*crypto.ECPoint, error) { - return crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.EcdsaPubX), - new(big.Int).SetBytes(m.EcdsaPubY)) -} - -func (m *DGRound1Message) UnmarshalVCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetVCommitment()) +// NewDGRound1Message constructs a *tss.Message with the given content. +func NewDGRound1Message(to []*tss.PartyID, from *tss.PartyID, ecdsaPub *crypto.ECPoint, vct cmt.HashCommitment, ssid []byte) *tss.Message { + return &tss.Message{ + From: from, + To: to, + IsBroadcast: true, + Content: &DGRound1Message{ + ECDSAPub: ecdsaPub, + VCommitment: vct, + SSID: ssid, + }, + } } -func (m *DGRound1Message) UnmarshalSSID() []byte { - return m.GetSsid() +// DGRound2Message1 is broadcast by new committee: Paillier key + Pedersen params + proofs. +type DGRound2Message1 struct { + PaillierPK *paillier.PublicKey + NTilde *big.Int + H1 *big.Int + H2 *big.Int + ModProof *modproof.ProofMod // nil in SNARK mode + DLNProof1 *dlnproof.Proof // nil in SNARK mode + DLNProof2 *dlnproof.Proof // nil in SNARK mode } -// ----- // - -func NewDGRound2Message1( - to []*tss.PartyID, - from *tss.PartyID, - paillierPK *paillier.PublicKey, - modProof *modproof.ProofMod, - NTildei, H1i, H2i *big.Int, - dlnProof1, dlnProof2 *dlnproof.Proof, -) (tss.ParsedMessage, error) { - meta := tss.MessageRouting{ +// ValidateBasic checks that required fields of DGRound2Message1 are non-nil. +func (m *DGRound2Message1) ValidateBasic() bool { + return m != nil && + m.PaillierPK != nil && m.PaillierPK.N != nil && m.PaillierPK.N.Sign() > 0 && + m.NTilde != nil && m.NTilde.Sign() > 0 && + m.H1 != nil && m.H1.Sign() > 0 && + m.H2 != nil && m.H2.Sign() > 0 +} + +// NewDGRound2Message1 constructs a *tss.Message with the given content. +func NewDGRound2Message1(to []*tss.PartyID, from *tss.PartyID, paillierPK *paillier.PublicKey, modProof *modproof.ProofMod, NTildei, H1i, H2i *big.Int, dlnProof1, dlnProof2 *dlnproof.Proof) *tss.Message { + return &tss.Message{ + From: from, + To: to, + IsBroadcast: true, + Content: &DGRound2Message1{ + PaillierPK: paillierPK, + NTilde: NTildei, + H1: H1i, + H2: H2i, + ModProof: modProof, + DLNProof1: dlnProof1, + DLNProof2: dlnProof2, + }, + } +} + +// DGRound2Message2 is an ACK broadcast from new to old committee. +type DGRound2Message2 struct{} + +// ValidateBasic checks that required fields of DGRound2Message2 are non-nil. +func (m *DGRound2Message2) ValidateBasic() bool { return m != nil } + +// NewDGRound2Message2 constructs a *tss.Message with the given content. +func NewDGRound2Message2(to []*tss.PartyID, from *tss.PartyID) *tss.Message { + return &tss.Message{ From: from, To: to, IsBroadcast: true, - IsToOldCommittee: false, - } - modPfBzs := modProof.Bytes() - dlnProof1Bz, err := dlnProof1.Serialize() - if err != nil { - return nil, err - } - dlnProof2Bz, err := dlnProof2.Serialize() - if err != nil { - return nil, err - } - content := &DGRound2Message1{ - PaillierN: paillierPK.N.Bytes(), - ModProof: modPfBzs[:], - NTilde: NTildei.Bytes(), - H1: H1i.Bytes(), - H2: H2i.Bytes(), - Dlnproof_1: dlnProof1Bz, - Dlnproof_2: dlnProof2Bz, - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg), nil -} - -func (m *DGRound2Message1) ValidateBasic() bool { - return m != nil && - // use with NoProofFac() - // common.NonEmptyMultiBytes(m.ModProof, modproof.ProofModBytesParts) && - common.NonEmptyBytes(m.PaillierN) && - common.NonEmptyBytes(m.NTilde) && - common.NonEmptyBytes(m.H1) && - common.NonEmptyBytes(m.H2) && - // expected len of dln proof = sizeof(int64) + len(alpha) + len(t) - common.NonEmptyMultiBytes(m.GetDlnproof_1(), 2+(dlnproof.Iterations*2)) && - common.NonEmptyMultiBytes(m.GetDlnproof_2(), 2+(dlnproof.Iterations*2)) -} - -func (m *DGRound2Message1) UnmarshalPaillierPK() *paillier.PublicKey { - return &paillier.PublicKey{ - N: new(big.Int).SetBytes(m.PaillierN), + IsToOldCommittee: true, + Content: &DGRound2Message2{}, } } -func (m *DGRound2Message1) UnmarshalNTilde() *big.Int { - return new(big.Int).SetBytes(m.GetNTilde()) -} - -func (m *DGRound2Message1) UnmarshalH1() *big.Int { - return new(big.Int).SetBytes(m.GetH1()) +// DGRound3Message1 is P2P from old to new: VSS share. +type DGRound3Message1 struct { + Share *big.Int + ReceiverID []byte } -func (m *DGRound2Message1) UnmarshalH2() *big.Int { - return new(big.Int).SetBytes(m.GetH2()) +// ValidateBasic checks that required fields of DGRound3Message1 are non-nil. +func (m *DGRound3Message1) ValidateBasic() bool { + return m != nil && m.Share != nil && m.Share.Sign() > 0 && + len(m.ReceiverID) > 0 } -func (m *DGRound2Message1) UnmarshalModProof() (*modproof.ProofMod, error) { - return modproof.NewProofFromBytes(m.GetModProof()) +// NewDGRound3Message1 constructs a *tss.Message with the given content. +func NewDGRound3Message1(to *tss.PartyID, from *tss.PartyID, share *vss.Share) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &DGRound3Message1{ + Share: share.Share, + ReceiverID: to.Key, + }, + } } -func (m *DGRound2Message1) UnmarshalDLNProof1() (*dlnproof.Proof, error) { - return dlnproof.UnmarshalDLNProof(m.GetDlnproof_1()) +// DGRound3Message2 is broadcast by old committee: VSS decommitment. +type DGRound3Message2 struct { + VDeCommitment cmt.HashDeCommitment } -func (m *DGRound2Message1) UnmarshalDLNProof2() (*dlnproof.Proof, error) { - return dlnproof.UnmarshalDLNProof(m.GetDlnproof_2()) +// ValidateBasic checks that required fields of DGRound3Message2 are non-nil. +func (m *DGRound3Message2) ValidateBasic() bool { + return m != nil && len(m.VDeCommitment) >= 2 } -// ----- // - -func NewDGRound2Message2( - to []*tss.PartyID, - from *tss.PartyID, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: to, - IsBroadcast: true, - IsToOldCommittee: true, +// NewDGRound3Message2 constructs a *tss.Message with the given content. +func NewDGRound3Message2(to []*tss.PartyID, from *tss.PartyID, vdct cmt.HashDeCommitment) *tss.Message { + return &tss.Message{ + From: from, + To: to, + IsBroadcast: true, + Content: &DGRound3Message2{ + VDeCommitment: vdct, + }, } - content := &DGRound2Message2{} - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *DGRound2Message2) ValidateBasic() bool { - return true } -// ----- // - -func NewDGRound3Message1( - to *tss.PartyID, - from *tss.PartyID, - share *vss.Share, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - IsToOldCommittee: false, - } - content := &DGRound3Message1{ - Share: share.Share.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// DGRound4Message1 is P2P from new to new: FacProof. +type DGRound4Message1 struct { + FacProof *facproof.ProofFac // nil in SNARK mode + ReceiverID []byte } -func (m *DGRound3Message1) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.Share) +// ValidateBasic checks that required fields of DGRound4Message1 are non-nil. +func (m *DGRound4Message1) ValidateBasic() bool { + return m != nil && len(m.ReceiverID) > 0 } -// ----- // - -func NewDGRound3Message2( - to []*tss.PartyID, - from *tss.PartyID, - vdct cmt.HashDeCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: to, - IsBroadcast: true, - IsToOldCommittee: false, - } - vDctBzs := common.BigIntsToBytes(vdct) - content := &DGRound3Message2{ - VDecommitment: vDctBzs, +// NewDGRound4Message1 constructs a *tss.Message with the given content. +func NewDGRound4Message1(to *tss.PartyID, from *tss.PartyID, proof *facproof.ProofFac) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &DGRound4Message1{ + FacProof: proof, + ReceiverID: to.Key, + }, } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *DGRound3Message2) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.VDecommitment) -} - -func (m *DGRound3Message2) UnmarshalVDeCommitment() cmt.HashDeCommitment { - deComBzs := m.GetVDecommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) -} +// DGRound4Message2 is an ACK broadcast to both committees. +type DGRound4Message2 struct{} -// ----- // +// ValidateBasic checks that required fields of DGRound4Message2 are non-nil. +func (m *DGRound4Message2) ValidateBasic() bool { return m != nil } -func NewDGRound4Message2( - to []*tss.PartyID, - from *tss.PartyID, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewDGRound4Message2 constructs a *tss.Message with the given content. +func NewDGRound4Message2(to []*tss.PartyID, from *tss.PartyID) *tss.Message { + return &tss.Message{ From: from, To: to, IsBroadcast: true, IsToOldAndNewCommittees: true, + Content: &DGRound4Message2{}, } - content := &DGRound4Message2{} - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *DGRound4Message2) ValidateBasic() bool { - return true -} - -func NewDGRound4Message1( - to *tss.PartyID, - from *tss.PartyID, - proof *facproof.ProofFac, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - IsToOldCommittee: false, - } - pfBzs := proof.Bytes() - content := &DGRound4Message1{ - FacProof: pfBzs[:], - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *DGRound4Message1) ValidateBasic() bool { - return m != nil - // use with NoProofFac() - // && common.NonEmptyMultiBytes(m.GetFacProof(), facproof.ProofFacBytesParts) -} - -func (m *DGRound4Message1) UnmarshalFacProof() (*facproof.ProofFac, error) { - return facproof.NewProofFromBytes(m.GetFacProof()) } diff --git a/tss-lib/ecdsa/resharing/messages_constructor_test.go b/tss-lib/ecdsa/resharing/messages_constructor_test.go new file mode 100644 index 0000000..52eeaed --- /dev/null +++ b/tss-lib/ecdsa/resharing/messages_constructor_test.go @@ -0,0 +1,397 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "bytes" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestNewDGRound1MessageFields verifies that NewDGRound1Message populates +// all tss.Message envelope fields and content fields correctly. +func TestNewDGRound1MessageFields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[0] + to := pIDs[1:] + + ecdsaPub := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + vct := big.NewInt(777) + ssid := []byte("test-ssid-round1") + + msg := NewDGRound1Message(to, from, ecdsaPub, vct, ssid) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != len(to) { + t.Fatalf("To length: got %d, want %d", len(msg.To), len(to)) + } + for i, p := range to { + if msg.To[i] != p { + t.Fatalf("To[%d] mismatch", i) + } + } + if !msg.IsBroadcast { + t.Fatal("Round1 should be broadcast") + } + if msg.IsToOldAndNewCommittees { + t.Fatal("Round1 should NOT be IsToOldAndNewCommittees") + } + if msg.IsToOldCommittee { + t.Fatal("Round1 should NOT be IsToOldCommittee") + } + + // Content checks. + content, ok := msg.Content.(*DGRound1Message) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound1Message", msg.Content) + } + if content.ECDSAPub != ecdsaPub { + t.Fatal("ECDSAPub mismatch") + } + if content.VCommitment.Cmp(big.NewInt(777)) != 0 { + t.Fatalf("VCommitment: got %v, want 777", content.VCommitment) + } + if !bytes.Equal(content.SSID, ssid) { + t.Fatalf("SSID: got %x, want %x", content.SSID, ssid) + } + if !content.ValidateBasic() { + t.Fatal("constructed message should pass ValidateBasic") + } +} + +// TestNewDGRound2Message1Fields verifies that NewDGRound2Message1 populates +// all tss.Message envelope fields and content fields correctly. +func TestNewDGRound2Message1Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[1] + to := pIDs[2:] + + pk := &paillier.PublicKey{N: big.NewInt(12345)} + nTilde := big.NewInt(100) + h1 := big.NewInt(200) + h2 := big.NewInt(300) + + var dlnP1, dlnP2 dlnproof.Proof + for i := range dlnP1.Alpha { + dlnP1.Alpha[i] = big.NewInt(int64(i + 1)) + dlnP1.T[i] = big.NewInt(int64(i + 1)) + dlnP2.Alpha[i] = big.NewInt(int64(i + 100)) + dlnP2.T[i] = big.NewInt(int64(i + 100)) + } + + var mp modproof.ProofMod + mp.W = big.NewInt(10) + mp.A = big.NewInt(11) + mp.B = big.NewInt(12) + + msg := NewDGRound2Message1(to, from, pk, &mp, nTilde, h1, h2, &dlnP1, &dlnP2) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != len(to) { + t.Fatalf("To length: got %d, want %d", len(msg.To), len(to)) + } + if !msg.IsBroadcast { + t.Fatal("Round2Message1 should be broadcast") + } + if msg.IsToOldCommittee { + t.Fatal("Round2Message1 should NOT be IsToOldCommittee") + } + if msg.IsToOldAndNewCommittees { + t.Fatal("Round2Message1 should NOT be IsToOldAndNewCommittees") + } + + // Content checks. + content, ok := msg.Content.(*DGRound2Message1) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound2Message1", msg.Content) + } + if content.PaillierPK.N.Cmp(big.NewInt(12345)) != 0 { + t.Fatalf("PaillierPK.N: got %v, want 12345", content.PaillierPK.N) + } + if content.NTilde.Cmp(nTilde) != 0 { + t.Fatal("NTilde mismatch") + } + if content.H1.Cmp(h1) != 0 { + t.Fatal("H1 mismatch") + } + if content.H2.Cmp(h2) != 0 { + t.Fatal("H2 mismatch") + } + if content.DLNProof1 == nil || content.DLNProof2 == nil { + t.Fatal("DLN proofs should be non-nil") + } + if content.ModProof == nil { + t.Fatal("ModProof should be non-nil") + } + if content.ModProof.W.Cmp(big.NewInt(10)) != 0 { + t.Fatal("ModProof.W mismatch") + } + if !content.ValidateBasic() { + t.Fatal("constructed message should pass ValidateBasic") + } + + // Nil proofs (SNARK mode). + msgNil := NewDGRound2Message1(to, from, pk, nil, nTilde, h1, h2, nil, nil) + contentNil := msgNil.Content.(*DGRound2Message1) + if contentNil.DLNProof1 != nil || contentNil.DLNProof2 != nil { + t.Fatal("DLN proofs should be nil in SNARK mode") + } + if contentNil.ModProof != nil { + t.Fatal("ModProof should be nil in SNARK mode") + } + if !contentNil.ValidateBasic() { + t.Fatal("message with nil proofs should still pass ValidateBasic") + } +} + +// TestNewDGRound2Message2Fields verifies that NewDGRound2Message2 produces +// a broadcast ACK directed to the old committee. +func TestNewDGRound2Message2Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[2] + to := pIDs[:2] + + msg := NewDGRound2Message2(to, from) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != len(to) { + t.Fatalf("To length: got %d, want %d", len(msg.To), len(to)) + } + if !msg.IsBroadcast { + t.Fatal("Round2Message2 should be broadcast") + } + if !msg.IsToOldCommittee { + t.Fatal("Round2Message2 should be IsToOldCommittee") + } + if msg.IsToOldAndNewCommittees { + t.Fatal("Round2Message2 should NOT be IsToOldAndNewCommittees") + } + + // Content checks. + content, ok := msg.Content.(*DGRound2Message2) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound2Message2", msg.Content) + } + if !content.ValidateBasic() { + t.Fatal("constructed ACK should pass ValidateBasic") + } +} + +// TestNewDGRound3Message1Fields verifies that NewDGRound3Message1 produces +// a P2P message with correct Share and ReceiverID. +func TestNewDGRound3Message1Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[0] + to := pIDs[1] + + share := &vss.Share{ + Threshold: 1, + ID: big.NewInt(7), + Share: big.NewInt(999), + } + + msg := NewDGRound3Message1(to, from, share) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != 1 || msg.To[0] != to { + t.Fatalf("To: got %v, want [%v]", msg.To, to) + } + if msg.IsBroadcast { + t.Fatal("Round3Message1 should NOT be broadcast (P2P)") + } + if msg.IsToOldCommittee { + t.Fatal("Round3Message1 should NOT be IsToOldCommittee") + } + if msg.IsToOldAndNewCommittees { + t.Fatal("Round3Message1 should NOT be IsToOldAndNewCommittees") + } + + // Content checks. + content, ok := msg.Content.(*DGRound3Message1) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound3Message1", msg.Content) + } + if content.Share.Cmp(big.NewInt(999)) != 0 { + t.Fatalf("Share: got %v, want 999", content.Share) + } + if !bytes.Equal(content.ReceiverID, to.Key) { + t.Fatalf("ReceiverID: got %x, want %x", content.ReceiverID, to.Key) + } + if !content.ValidateBasic() { + t.Fatal("constructed message should pass ValidateBasic") + } +} + +// TestNewDGRound3Message2Fields verifies that NewDGRound3Message2 produces +// a broadcast message with the correct VDeCommitment. +func TestNewDGRound3Message2Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[0] + to := pIDs[1:] + + vdct := cmt.HashDeCommitment{big.NewInt(10), big.NewInt(20), big.NewInt(30)} + + msg := NewDGRound3Message2(to, from, vdct) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != len(to) { + t.Fatalf("To length: got %d, want %d", len(msg.To), len(to)) + } + if !msg.IsBroadcast { + t.Fatal("Round3Message2 should be broadcast") + } + if msg.IsToOldCommittee { + t.Fatal("Round3Message2 should NOT be IsToOldCommittee") + } + if msg.IsToOldAndNewCommittees { + t.Fatal("Round3Message2 should NOT be IsToOldAndNewCommittees") + } + + // Content checks. + content, ok := msg.Content.(*DGRound3Message2) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound3Message2", msg.Content) + } + if len(content.VDeCommitment) != 3 { + t.Fatalf("VDeCommitment length: got %d, want 3", len(content.VDeCommitment)) + } + for i, v := range []int64{10, 20, 30} { + if content.VDeCommitment[i].Cmp(big.NewInt(v)) != 0 { + t.Fatalf("VDeCommitment[%d]: got %v, want %d", i, content.VDeCommitment[i], v) + } + } + if !content.ValidateBasic() { + t.Fatal("constructed message should pass ValidateBasic") + } +} + +// TestNewDGRound4Message1Fields verifies that NewDGRound4Message1 produces +// a P2P message with correct FacProof and ReceiverID. +func TestNewDGRound4Message1Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[2] + to := pIDs[0] + + proof := &facproof.ProofFac{ + P: big.NewInt(11), + Q: big.NewInt(13), + A: big.NewInt(17), + B: big.NewInt(19), + T: big.NewInt(23), + Sigma: big.NewInt(29), + Z1: big.NewInt(31), + Z2: big.NewInt(37), + W1: big.NewInt(41), + W2: big.NewInt(43), + V: big.NewInt(47), + } + + msg := NewDGRound4Message1(to, from, proof) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != 1 || msg.To[0] != to { + t.Fatalf("To: got %v, want [%v]", msg.To, to) + } + if msg.IsBroadcast { + t.Fatal("Round4Message1 should NOT be broadcast (P2P)") + } + if msg.IsToOldCommittee { + t.Fatal("Round4Message1 should NOT be IsToOldCommittee") + } + if msg.IsToOldAndNewCommittees { + t.Fatal("Round4Message1 should NOT be IsToOldAndNewCommittees") + } + + // Content checks. + content, ok := msg.Content.(*DGRound4Message1) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound4Message1", msg.Content) + } + if content.FacProof == nil { + t.Fatal("FacProof should be non-nil") + } + if content.FacProof.P.Cmp(big.NewInt(11)) != 0 { + t.Fatalf("FacProof.P: got %v, want 11", content.FacProof.P) + } + if !bytes.Equal(content.ReceiverID, to.Key) { + t.Fatalf("ReceiverID: got %x, want %x", content.ReceiverID, to.Key) + } + if !content.ValidateBasic() { + t.Fatal("constructed message should pass ValidateBasic") + } + + // Nil proof (SNARK mode). + msgNil := NewDGRound4Message1(to, from, nil) + contentNil := msgNil.Content.(*DGRound4Message1) + if contentNil.FacProof != nil { + t.Fatal("FacProof should be nil in SNARK mode") + } + if !contentNil.ValidateBasic() { + t.Fatal("message with nil FacProof should still pass ValidateBasic") + } +} + +// TestNewDGRound4Message2Fields verifies that NewDGRound4Message2 produces +// a broadcast ACK directed to both old and new committees. +func TestNewDGRound4Message2Fields(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(4) + from := pIDs[3] + to := pIDs[:3] + + msg := NewDGRound4Message2(to, from) + + // Envelope checks. + if msg.From != from { + t.Fatal("From mismatch") + } + if len(msg.To) != len(to) { + t.Fatalf("To length: got %d, want %d", len(msg.To), len(to)) + } + if !msg.IsBroadcast { + t.Fatal("Round4Message2 should be broadcast") + } + if msg.IsToOldCommittee { + t.Fatal("Round4Message2 should NOT be IsToOldCommittee (it goes to both)") + } + if !msg.IsToOldAndNewCommittees { + t.Fatal("Round4Message2 should be IsToOldAndNewCommittees") + } + + // Content checks. + content, ok := msg.Content.(*DGRound4Message2) + if !ok { + t.Fatalf("Content type: got %T, want *DGRound4Message2", msg.Content) + } + if !content.ValidateBasic() { + t.Fatal("constructed ACK should pass ValidateBasic") + } +} diff --git a/tss-lib/ecdsa/resharing/messages_test.go b/tss-lib/ecdsa/resharing/messages_test.go new file mode 100644 index 0000000..8574f0f --- /dev/null +++ b/tss-lib/ecdsa/resharing/messages_test.go @@ -0,0 +1,74 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestValidateBasicAllResharingMessages(t *testing.T) { + pt := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + + tests := []struct { + name string + valid interface{ ValidateBasic() bool } + bad interface{ ValidateBasic() bool } + }{ + { + "DGRound1Message", + &DGRound1Message{ECDSAPub: pt, VCommitment: big.NewInt(1), SSID: []byte("s")}, + &DGRound1Message{}, + }, + { + "DGRound2Message1", + &DGRound2Message1{PaillierPK: &paillier.PublicKey{N: big.NewInt(100)}, NTilde: big.NewInt(1), H1: big.NewInt(2), H2: big.NewInt(3)}, + &DGRound2Message1{}, + }, + { + "DGRound2Message2", + &DGRound2Message2{}, + (*DGRound2Message2)(nil), + }, + { + "DGRound3Message1", + &DGRound3Message1{Share: big.NewInt(1), ReceiverID: []byte("r")}, + &DGRound3Message1{}, + }, + { + "DGRound3Message2", + &DGRound3Message2{VDeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}}, + &DGRound3Message2{}, + }, + { + "DGRound4Message1", + &DGRound4Message1{ReceiverID: []byte("r")}, + &DGRound4Message1{}, + }, + { + "DGRound4Message2", + &DGRound4Message2{}, + (*DGRound4Message2)(nil), + }, + } + + for _, tt := range tests { + t.Run(tt.name+"_valid", func(t *testing.T) { + if !tt.valid.ValidateBasic() { + t.Fatal("valid should pass") + } + }) + t.Run(tt.name+"_invalid", func(t *testing.T) { + if tt.bad.ValidateBasic() { + t.Fatal("invalid should fail") + } + }) + } +} diff --git a/tss-lib/ecdsa/resharing/round2_round5_negative_test.go b/tss-lib/ecdsa/resharing/round2_round5_negative_test.go new file mode 100644 index 0000000..20490cd --- /dev/null +++ b/tss-lib/ecdsa/resharing/round2_round5_negative_test.go @@ -0,0 +1,935 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/testutil" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// reshareFixture holds everything produced by rounds 1-4 of an honest +// reshare, so that negative tests can corrupt individual messages before +// calling the target round. +type reshareFixture struct { + n, threshold int + oldKeys []keygen.LocalPartySaveData + oldStates []*ReshareState + newStates []*ReshareState + oldR1Msgs []*tss.Message + newR2Msg1s []*tss.Message + newR2Msg2s []*tss.Message + oldR3P2P [][]*tss.Message + oldR3Bcast []*tss.Message + newR4P2P [][]*tss.Message + newR4Bcast []*tss.Message + newPIDs tss.SortedPartyIDs + oldPIDs tss.SortedPartyIDs +} + +// buildReshareFixture runs an honest keygen(3) followed by reshare +// rounds 1-4 with all proofs disabled (SNARK mode), returning the +// intermediate state needed to test Round2 and Round5 error paths. +func buildReshareFixture(t *testing.T) *reshareFixture { + t.Helper() + const n = 3 + const threshold = 1 // 2-of-3 + + // ---- Keygen ---- + preParamsOld := testutil.LoadPreParams(t, n) + oldPIDs := tss.GenerateTestPartyIDs(n) + oldCtx := tss.NewPeerContext(oldPIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), oldCtx, oldPIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParamsOld[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + + oldKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + oldKeys[i] = *out.Save + } + + // ---- Reshare: 3 old -> 3 new (disjoint), all proofs disabled ---- + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + // Round 2 + newR2Msg1s := make([]*tss.Message, n) + newR2Msg2s := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := ReshareRound2(newStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound2Message1: + newR2Msg1s[i] = pm + case *DGRound2Message2: + newR2Msg2s[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, err := ReshareRound2(oldStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(old)[%d]: %v", i, err) + } + } + for i := 0; i < n; i++ { + if newR2Msg1s[i] == nil { + newR2Msg1s[i] = newStates[i].temp.dgRound2Message1s[i] + } + if newR2Msg2s[i] == nil { + newR2Msg2s[i] = newStates[i].temp.dgRound2Message2s[i] + } + } + + // Round 3 + oldR3P2P := make([][]*tss.Message, n) + oldR3Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + oldR3P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound3(oldStates[i], newR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(old)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound3Message1: + for _, to := range pm.To { + oldR3P2P[to.Index][i] = pm + } + case *DGRound3Message2: + oldR3Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound3(newStates[i], newR2Msg2s) + } + + // Round 4 + newR4P2P := make([][]*tss.Message, n) + newR4Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + newR4P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound4(context.Background(), newStates[i], newR2Msg1s, oldR3P2P[i], oldR3Bcast) + if err != nil { + t.Fatalf("ReshareRound4(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound4Message1: + for _, to := range pm.To { + newR4P2P[to.Index][i] = pm + } + case *DGRound4Message2: + newR4Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound4(context.Background(), oldStates[i], newR2Msg1s, nil, nil) + } + for i := 0; i < n; i++ { + if newR4Bcast[i] == nil { + newR4Bcast[i] = newStates[i].temp.dgRound4Message2s[i] + } + } + + return &reshareFixture{ + n: n, + threshold: threshold, + oldKeys: oldKeys, + oldStates: oldStates, + newStates: newStates, + oldR1Msgs: oldR1Msgs, + newR2Msg1s: newR2Msg1s, + newR2Msg2s: newR2Msg2s, + oldR3P2P: oldR3P2P, + oldR3Bcast: oldR3Bcast, + newR4P2P: newR4P2P, + newR4Bcast: newR4Bcast, + newPIDs: newPIDs, + oldPIDs: oldPIDs, + } +} + +// cloneR4P2PSlice returns a deep copy of the P2P message slice for +// one new party so that corruption in negative tests is isolated. +func cloneR4P2PSlice(src []*tss.Message) []*tss.Message { + dst := make([]*tss.Message, len(src)) + for j, m := range src { + if m == nil { + continue + } + orig := m.Content.(*DGRound4Message1) + dst[j] = &tss.Message{ + From: m.From, + To: m.To, + Content: &DGRound4Message1{ + FacProof: orig.FacProof, + ReceiverID: append([]byte(nil), orig.ReceiverID...), + }, + } + } + return dst +} + +// --------------------------------------------------------------------------- +// Round 5 negative tests +// --------------------------------------------------------------------------- + +// TestReshareRound5RejectsReceiverIDMismatch corrupts the ReceiverID +// in a DGRound4Message1 and verifies that Round5 rejects it with the +// expected "receiverId mismatch" error. +func TestReshareRound5RejectsReceiverIDMismatch(t *testing.T) { + fix := buildReshareFixture(t) + + // Target: new party 0. Corrupt the ReceiverID from party 1. + target := 0 + corrupted := cloneR4P2PSlice(fix.newR4P2P[target]) + + // Find the first non-self, non-nil message to corrupt. + corruptIdx := -1 + for j := 0; j < fix.n; j++ { + if j == target && corrupted[j] == nil { + continue + } + if j != target && corrupted[j] != nil { + corruptIdx = j + break + } + } + if corruptIdx < 0 { + t.Fatal("no P2P message to corrupt") + } + // Replace ReceiverID with garbage bytes. + corrupted[corruptIdx].Content.(*DGRound4Message1).ReceiverID = []byte("wrong-receiver-id") + + _, err := ReshareRound5(fix.newStates[target], corrupted, fix.newR4Bcast) + if err == nil { + t.Fatal("expected error for corrupted ReceiverID, got nil") + } + if !strings.Contains(err.Error(), "receiverId mismatch") { + t.Fatalf("expected 'receiverId mismatch' error, got: %v", err) + } + requireCulprit(t, err, corruptIdx) + t.Logf("correctly rejected corrupted ReceiverID: %v", err) +} + +// TestReshareRound5RejectsNilFacProof sets the FacProof to nil in a +// DGRound4Message1 and verifies that Round5 rejects it when FacProof +// verification is enabled. +func TestReshareRound5RejectsNilFacProof(t *testing.T) { + // We need a fixture with FacProof enabled (NoProofFac = false). + // Rebuild with proofs enabled so the path through proof verification + // is exercised. + fix := buildReshareFixtureWithFacProof(t) + + target := 0 + corrupted := cloneR4P2PSlice(fix.newR4P2P[target]) + + corruptIdx := -1 + for j := 0; j < fix.n; j++ { + if j != target && corrupted[j] != nil { + corruptIdx = j + break + } + } + if corruptIdx < 0 { + t.Fatal("no P2P message to corrupt") + } + corrupted[corruptIdx].Content.(*DGRound4Message1).FacProof = nil + + _, err := ReshareRound5(fix.newStates[target], corrupted, fix.newR4Bcast) + if err == nil { + t.Fatal("expected error for nil FacProof, got nil") + } + if !strings.Contains(err.Error(), "facProof missing") { + t.Fatalf("expected 'facProof missing' error, got: %v", err) + } + requireCulprit(t, err, corruptIdx) + t.Logf("correctly rejected nil FacProof: %v", err) +} + +// TestReshareRound5RejectsBadFacProof corrupts a FacProof field in a +// DGRound4Message1 and verifies that Round5 rejects it when FacProof +// verification is enabled. +func TestReshareRound5RejectsBadFacProof(t *testing.T) { + fix := buildReshareFixtureWithFacProof(t) + + target := 0 + corrupted := cloneR4P2PSlice(fix.newR4P2P[target]) + + corruptIdx := -1 + for j := 0; j < fix.n; j++ { + if j != target && corrupted[j] != nil { + corruptIdx = j + break + } + } + if corruptIdx < 0 { + t.Fatal("no P2P message to corrupt") + } + proof := corrupted[corruptIdx].Content.(*DGRound4Message1).FacProof + if proof == nil { + t.Fatal("expected non-nil FacProof in fixture with proofs enabled") + } + // Corrupt the proof by flipping a field. The P field is part of the + // proof verification equation; adding 1 invalidates it. + proof.P = new(big.Int).Add(proof.P, big.NewInt(1)) + + _, err := ReshareRound5(fix.newStates[target], corrupted, fix.newR4Bcast) + if err == nil { + t.Fatal("expected error for corrupted FacProof, got nil") + } + if !strings.Contains(err.Error(), "facProof verify failed") { + t.Fatalf("expected 'facProof verify failed' error, got: %v", err) + } + requireCulprit(t, err, corruptIdx) + t.Logf("correctly rejected corrupted FacProof: %v", err) +} + +// buildReshareFixtureWithFacProof is identical to buildReshareFixture +// except FacProof generation and verification are enabled (only DLN +// and Mod proofs are disabled). This is needed because the default +// fixture disables all proofs. +func buildReshareFixtureWithFacProof(t *testing.T) *reshareFixture { + t.Helper() + const n = 3 + const threshold = 1 + + // ---- Keygen ---- + preParamsOld := testutil.LoadPreParams(t, n) + oldPIDs := tss.GenerateTestPartyIDs(n) + oldCtx := tss.NewPeerContext(oldPIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), oldCtx, oldPIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParamsOld[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + oldKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + oldKeys[i] = *out.Save + } + + // ---- Reshare with FacProof ENABLED (DLN+Mod disabled) ---- + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + // FacProof enabled (no SetNoProofFac call) + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + // FacProof enabled + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + // Round 2 + newR2Msg1s := make([]*tss.Message, n) + newR2Msg2s := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := ReshareRound2(newStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound2Message1: + newR2Msg1s[i] = pm + case *DGRound2Message2: + newR2Msg2s[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, err := ReshareRound2(oldStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(old)[%d]: %v", i, err) + } + } + for i := 0; i < n; i++ { + if newR2Msg1s[i] == nil { + newR2Msg1s[i] = newStates[i].temp.dgRound2Message1s[i] + } + if newR2Msg2s[i] == nil { + newR2Msg2s[i] = newStates[i].temp.dgRound2Message2s[i] + } + } + + // Round 3 + oldR3P2P := make([][]*tss.Message, n) + oldR3Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + oldR3P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound3(oldStates[i], newR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(old)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound3Message1: + for _, to := range pm.To { + oldR3P2P[to.Index][i] = pm + } + case *DGRound3Message2: + oldR3Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound3(newStates[i], newR2Msg2s) + } + + // Round 4 (FacProof enabled — generates real proofs) + newR4P2P := make([][]*tss.Message, n) + newR4Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + newR4P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound4(context.Background(), newStates[i], newR2Msg1s, oldR3P2P[i], oldR3Bcast) + if err != nil { + t.Fatalf("ReshareRound4(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound4Message1: + for _, to := range pm.To { + newR4P2P[to.Index][i] = pm + } + case *DGRound4Message2: + newR4Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound4(context.Background(), oldStates[i], newR2Msg1s, nil, nil) + } + for i := 0; i < n; i++ { + if newR4Bcast[i] == nil { + newR4Bcast[i] = newStates[i].temp.dgRound4Message2s[i] + } + } + + return &reshareFixture{ + n: n, + threshold: threshold, + oldKeys: oldKeys, + oldStates: oldStates, + newStates: newStates, + oldR1Msgs: oldR1Msgs, + newR2Msg1s: newR2Msg1s, + newR2Msg2s: newR2Msg2s, + oldR3P2P: oldR3P2P, + oldR3Bcast: oldR3Bcast, + newR4P2P: newR4P2P, + newR4Bcast: newR4Bcast, + newPIDs: newPIDs, + oldPIDs: oldPIDs, + } +} + +// --------------------------------------------------------------------------- +// Round 2 negative tests +// --------------------------------------------------------------------------- + +// TestReshareRound2RejectsECDSAPubMismatch corrupts the ECDSAPub in +// one old party's R1 message so that it differs from the others, and +// verifies that Round2 rejects it with an "ecdsa pub key mismatch" +// error. +func TestReshareRound2RejectsECDSAPubMismatch(t *testing.T) { + const n = 3 + const threshold = 1 + + // ---- Keygen ---- + preParamsOld := testutil.LoadPreParams(t, n) + oldPIDs := tss.GenerateTestPartyIDs(n) + oldCtx := tss.NewPeerContext(oldPIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), oldCtx, oldPIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParamsOld[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + oldKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + oldKeys[i] = *out.Save + } + + // ---- Reshare Round 1 ---- + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + // Corrupt ECDSAPub in the second old party's R1 message: + // Replace it with a different valid curve point (generator * 42). + fakePoint := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + corruptedR1Msgs := make([]*tss.Message, n) + copy(corruptedR1Msgs, oldR1Msgs) + + // Pick a message index to corrupt (index 1 — the second old party). + // We need to create a new message with the corrupted ECDSAPub. + origMsg := oldR1Msgs[1] + origContent := origMsg.Content.(*DGRound1Message) + corruptedR1Msgs[1] = &tss.Message{ + From: origMsg.From, + To: origMsg.To, + IsBroadcast: origMsg.IsBroadcast, + Content: &DGRound1Message{ + ECDSAPub: fakePoint, + VCommitment: origContent.VCommitment, + SSID: origContent.SSID, + }, + } + + // Round 2 on new party 0 should reject the mismatch. + _, err := ReshareRound2(newStates[0], corruptedR1Msgs) + if err == nil { + t.Fatal("expected error for ECDSAPub mismatch, got nil") + } + if !strings.Contains(err.Error(), "ecdsa pub key mismatch") { + t.Fatalf("expected 'ecdsa pub key mismatch' error, got: %v", err) + } + t.Logf("correctly rejected ECDSAPub mismatch: %v", err) +} + +// TestReshareRound2RejectsNilECDSAPub sets ECDSAPub to nil in one old +// party's R1 message. Exercises the nil guard at round_fn.go:205-206. +func TestReshareRound2RejectsNilECDSAPub(t *testing.T) { + fix := setupThroughRound1ForRound2(t) + + corruptedR1 := make([]*tss.Message, len(fix.oldR1Msgs)) + copy(corruptedR1, fix.oldR1Msgs) + + // Set party 1's ECDSAPub to nil. + orig := fix.oldR1Msgs[1] + origContent := orig.Content.(*DGRound1Message) + corruptedR1[1] = &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: &DGRound1Message{ + ECDSAPub: nil, + VCommitment: origContent.VCommitment, + SSID: origContent.SSID, + }, + } + + _, err := ReshareRound2(fix.newStates[0], corruptedR1) + if err == nil { + t.Fatal("expected error for nil ECDSAPub, got nil") + } + if !strings.Contains(err.Error(), "ecdsa pub nil") { + t.Fatalf("expected 'ecdsa pub nil' error, got: %v", err) + } + t.Logf("correctly rejected nil ECDSAPub: %v", err) +} + +// TestReshareRound2RejectsSSIDMismatch corrupts the SSID in one old +// party's R1 message so it differs from the others. Exercises the +// SSID consistency check at round_fn.go:195-197. +func TestReshareRound2RejectsSSIDMismatch(t *testing.T) { + fix := setupThroughRound1ForRound2(t) + + corruptedR1 := make([]*tss.Message, len(fix.oldR1Msgs)) + copy(corruptedR1, fix.oldR1Msgs) + + // Corrupt party 1's SSID to differ from party 0's. + orig := fix.oldR1Msgs[1] + origContent := orig.Content.(*DGRound1Message) + corruptedR1[1] = &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: &DGRound1Message{ + ECDSAPub: origContent.ECDSAPub, + VCommitment: origContent.VCommitment, + SSID: []byte("wrong-ssid-value"), + }, + } + + _, err := ReshareRound2(fix.newStates[0], corruptedR1) + if err == nil { + t.Fatal("expected error for SSID mismatch, got nil") + } + if !strings.Contains(err.Error(), "ssid mismatch") { + t.Fatalf("expected 'ssid mismatch' error, got: %v", err) + } + requireCulprit(t, err, 1) // corrupted old party 1 + t.Logf("correctly rejected SSID mismatch: %v", err) +} + +// TestReshareRound2RejectsStalePreParams corrupts the new party's pre-params +// so that Validate() passes but ValidateWithProof() fails (nil Alpha). +// Exercises the guard at round_fn.go:222-223. +func TestReshareRound2RejectsStalePreParams(t *testing.T) { + fix := setupThroughRound1ForRound2(t) + + // Corrupt new party 0's save data: nil out Alpha so Validate() passes + // (it only checks PaillierSK, NTilde, H1, H2) but ValidateWithProof() + // fails (it additionally checks Alpha, Beta, P, Q). + fix.newStates[0].save.Alpha = nil + + _, err := ReshareRound2(fix.newStates[0], fix.oldR1Msgs) + if err == nil { + t.Fatal("expected error for stale preParams, got nil") + } + if !strings.Contains(err.Error(), "preParams failed validation") { + t.Fatalf("expected 'preParams failed validation' error, got: %v", err) + } + t.Logf("correctly rejected stale preParams: %v", err) +} + +// round2SetupFixture holds state for Round2 negative tests. +type round2SetupFixture struct { + oldR1Msgs []*tss.Message + newStates []*ReshareState +} + +// setupThroughRound1ForRound2 runs keygen(3) + reshare Round1 for 3 old → 3 +// new parties and returns the R1 messages + new-committee states ready for +// Round2 corruption tests. +func setupThroughRound1ForRound2(t *testing.T) *round2SetupFixture { + t.Helper() + const n = 3 + const threshold = 1 + + // Keygen + preParamsOld := testutil.LoadPreParams(t, n) + oldPIDs := tss.GenerateTestPartyIDs(n) + oldCtx := tss.NewPeerContext(oldPIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), oldCtx, oldPIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParamsOld[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + oldKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + oldKeys[i] = *out.Save + } + + // Reshare Round 1 + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + _ = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + return &round2SetupFixture{ + oldR1Msgs: oldR1Msgs, + newStates: newStates, + } +} diff --git a/tss-lib/ecdsa/resharing/round4_newxi_zero_test.go b/tss-lib/ecdsa/resharing/round4_newxi_zero_test.go new file mode 100644 index 0000000..30ccc2d --- /dev/null +++ b/tss-lib/ecdsa/resharing/round4_newxi_zero_test.go @@ -0,0 +1,156 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestReshareRound4RejectsNewXiZero exercises the "newXi is zero" check at +// round_fn.go lines 506-508. This condition occurs when the sum of all old +// parties' VSS shares (evaluated at the new party's key) is zero mod q, +// meaning the new party would receive a degenerate (zero) secret share. +// +// Triggering this through the public API is non-trivial because each +// individual share must pass Feldman VSS verification before contributing to +// the sum. The test constructs a scenario where: +// +// 1. Old parties 0 and 1 produce honest shares for new party 0. +// 2. Old party 2's share is replaced with a value that makes the total sum +// exactly zero mod q: share2' = q - (share0 + share1) mod q. +// 3. Old party 2's VSS commitment polynomial is reconstructed from scratch +// to be consistent with the forged share, so Feldman VSS passes. +// 4. The R1 commitment hash and R3 decommitment are updated to match. +// +// This is a COLLUDING-ADVERSARY scenario: old party 2 is fully malicious and +// crafts its polynomial to produce a zero-sum share for the target new party. +func TestReshareRound4RejectsNewXiZero(t *testing.T) { + fix := setupThroughRound3(t) + + ec := tss.S256() + q := ec.Params().N + modQ := common.ModInt(q) + + const ( + newVictim = 0 // new party index that will receive zero xi + corruptOld = 2 // old party index we corrupt + ) + + // Step 1: Extract the honest shares from all old parties to new party 0. + shares := make([]*big.Int, reshareN) + for j := 0; j < reshareN; j++ { + r3p2p := fix.OldR3P2P[newVictim][j] + shares[j] = r3p2p.Content.(*DGRound3Message1).Share + } + + // Step 2: Compute the current sum and the forged share for old party 2. + partialSum := modQ.Add(shares[0], shares[1]) + // desiredShare2 = q - partialSum, so that share0 + share1 + desiredShare2 = 0 mod q. + desiredShare2 := new(big.Int).Sub(q, partialSum) + desiredShare2.Mod(desiredShare2, q) + if desiredShare2.Sign() == 0 { + // This would mean share0 + share1 = 0 mod q, which is astronomically + // unlikely (~2^{-256}). If it ever happens, the individual VSS Verify + // would reject a zero share anyway. + t.Fatal("partialSum == 0 mod q; astronomically unlikely, test assumptions broken") + } + + // Step 3: Construct a new degree-1 polynomial for old party 2 that evaluates + // to desiredShare2 at the new party's key. + // + // Polynomial: f(x) = a0 + a1*x, threshold = 1. + // We choose a1 randomly, then a0 = desiredShare2 - a1*P mod q. + P := fix.NewPIDs[newVictim].KeyInt() // evaluation point + a1 := common.GetRandomPositiveInt(fix.OldStates[corruptOld].params.Rand(), q) + a1P := modQ.Mul(a1, P) + a0 := modQ.Sub(desiredShare2, a1P) // a0 = desiredShare2 - a1*P mod q + + // Verify: a0 + a1*P = desiredShare2 mod q (sanity check). + check := modQ.Add(a0, a1P) + if check.Cmp(desiredShare2) != 0 { + t.Fatalf("polynomial construction failed: a0+a1*P = %s, want %s", check, desiredShare2) + } + + // a0 must be non-zero for ScalarBaseMult to produce a valid curve point. + // a0 == 0 would mean desiredShare2 = a1*P, which is possible but extremely unlikely + // for random a1. If it happens, just pick a different a1. + if a0.Sign() == 0 { + t.Fatal("a0 == 0; astronomically unlikely") + } + + // Step 4: Compute the new Feldman VSS commitments V[0] = a0*G, V[1] = a1*G. + V0 := crypto.ScalarBaseMult(ec, a0) + V1 := crypto.ScalarBaseMult(ec, a1) + + // Step 5: Build the updated R3 broadcast (decommitment) for old party 2. + // The decommitment D = [randomness, V0.X, V0.Y, V1.X, V1.Y]. + // Extract the original randomness from the existing decommitment. + origR3Bcast := fix.OldR3Bcast[corruptOld].Content.(*DGRound3Message2) + origD := origR3Bcast.VDeCommitment + // The full D stored in the commitment includes [r, secrets...]. + // DeCommit() strips the first element (randomness) and returns secrets. + // But VDeCommitment in the message IS the full D (including randomness). + // Looking at the code: in Round1, temp.VD = vCmt.D (which is [r, flatVs...]). + // In Round3, NewDGRound3Message2 passes temp.VD as VDeCommitment. + // In Round4, the verification uses vDj directly from the message, and + // cmtDeCmt.DeCommit() strips the randomness element. + // So origD[0] is the randomness, and origD[1:] are the flattened points. + randomness := origD[0] + + // Build the new decommitment. + newFlatVs := []*big.Int{V0.X(), V0.Y(), V1.X(), V1.Y()} + newCmt := commitments.NewHashCommitmentWithRandomness(randomness, newFlatVs...) + + // Step 6: Update the R1 message's VCommitment for old party 2 in the + // new party 0's stored messages. + r1stored := fix.NewStates[newVictim].temp.dgRound1Messages[corruptOld] + r1content := r1stored.Content.(*DGRound1Message) + r1content.VCommitment = newCmt.C + + // Step 7: Update the R3 broadcast (decommitment) for old party 2. + r3Bcast := copyR3BcastSlice(fix.OldR3Bcast) + r3Bcast[corruptOld] = &tss.Message{ + From: fix.OldR3Bcast[corruptOld].From, + To: fix.OldR3Bcast[corruptOld].To, + IsBroadcast: true, + Content: &DGRound3Message2{VDeCommitment: newCmt.D}, + } + + // Step 8: Update the R3 P2P share for old party 2 → new party 0. + r3P2P := copyR3P2PSlice(fix.OldR3P2P[newVictim]) + origP2P := r3P2P[corruptOld].Content.(*DGRound3Message1) + r3P2P[corruptOld] = &tss.Message{ + From: fix.OldR3P2P[newVictim][corruptOld].From, + To: fix.OldR3P2P[newVictim][corruptOld].To, + Content: &DGRound3Message1{ + Share: desiredShare2, + ReceiverID: origP2P.ReceiverID, + }, + } + + // Step 9: Call ReshareRound4 and expect "newXi is zero" error. + _, err := ReshareRound4( + context.Background(), + fix.NewStates[newVictim], + fix.NewR2Msg1s, + r3P2P, + r3Bcast, + ) + if err == nil { + t.Fatal("expected error from newXi == 0, got nil") + } + if !strings.Contains(err.Error(), "newXi is zero") { + t.Fatalf("expected 'newXi is zero' error, got: %v", err) + } + t.Logf("correctly rejected zero newXi: %v", err) +} diff --git a/tss-lib/ecdsa/resharing/round4_param_negative_test.go b/tss-lib/ecdsa/resharing/round4_param_negative_test.go new file mode 100644 index 0000000..ca32234 --- /dev/null +++ b/tss-lib/ecdsa/resharing/round4_param_negative_test.go @@ -0,0 +1,309 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// expectRound4ParamError calls ReshareRound4 on new-committee party 0 with the +// given R2 messages and asserts that the error contains the expected substring +// and that the culprit has the expected index. +func expectRound4ParamError(t *testing.T, fix *ReshareFixture, msgs []*tss.Message, wantErrSubstr string, wantCulpritIdx int) { + t.Helper() + _, err := ReshareRound4(context.Background(), fix.NewStates[0], msgs, fix.OldR3P2P[0], fix.OldR3Bcast) + if err == nil { + t.Fatalf("expected error containing %q, got nil", wantErrSubstr) + } + if !strings.Contains(err.Error(), wantErrSubstr) { + t.Fatalf("expected error containing %q, got: %v", wantErrSubstr, err) + } + requireCulprit(t, err, wantCulpritIdx) +} + +// r4VictimIdx is the index of the party whose R2 message we corrupt. +// We pick party 1 (not party 0, which is the verifier). +const r4VictimIdx = 1 + +// ---------- Individual parameter validation tests ---------- + +func TestRound4RejectsPaillierNInsufficientBits(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + bad.Content.(*DGRound2Message1).PaillierPK.N = big.NewInt(1023) // tiny + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "paillier N insufficient bits", r4VictimIdx) +} + +func TestRound4RejectsEvenPaillierN(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + n := bad.Content.(*DGRound2Message1).PaillierPK.N + n.SetBit(n, 0, 0) // make even + n.SetBit(n, 2047, 1) // keep >= 2048 bits + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "even paillier N", r4VictimIdx) +} + +func TestRound4RejectsPrimePaillierN(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + // RFC 3526 2048-bit MODP prime. + prime, _ := new(big.Int).SetString( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"+ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"+ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"+ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"+ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"+ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + if prime.BitLen() != 2048 || !prime.ProbablyPrime(20) { + t.Fatal("test setup: expected a 2048-bit prime") + } + bad.Content.(*DGRound2Message1).PaillierPK.N = prime + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "prime paillier N", r4VictimIdx) +} + +func TestRound4RejectsPerfectSquarePaillierN(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + // Use the victim's own P to construct p*p (a perfect square). + p := fix.NewStates[r4VictimIdx].save.P + pp := new(big.Int).Mul(p, p) + if pp.BitLen() < 2048 { + q := fix.NewStates[r4VictimIdx].save.Q + pp = new(big.Int).Mul(q, q) + } + if pp.BitLen() < 2048 { + t.Skip("neither p*p nor q*q is >= 2048 bits; skipping") + } + bad.Content.(*DGRound2Message1).PaillierPK.N = pp + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "perfect-square paillier N", r4VictimIdx) +} + +func TestRound4RejectsH1EqualsH2(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + content := bad.Content.(*DGRound2Message1) + content.H2 = new(big.Int).Set(content.H1) // H1 == H2 + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "h1j == h2j", r4VictimIdx) +} + +func TestRound4RejectsH1IsOne(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + bad.Content.(*DGRound2Message1).H1 = big.NewInt(1) + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "h1j or h2j is 1", r4VictimIdx) +} + +func TestRound4RejectsH2IsOne(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + bad.Content.(*DGRound2Message1).H2 = big.NewInt(1) + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "h1j or h2j is 1", r4VictimIdx) +} + +func TestRound4RejectsNTildeInsufficientBits(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + bad.Content.(*DGRound2Message1).NTilde = big.NewInt(999) // tiny + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "NTildej insufficient bits", r4VictimIdx) +} + +func TestRound4RejectsEvenNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + nt := bad.Content.(*DGRound2Message1).NTilde + nt.SetBit(nt, 0, 0) // make even + nt.SetBit(nt, 2047, 1) // keep >= 2048 bits + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "even NTildej", r4VictimIdx) +} + +func TestRound4RejectsPrimeNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + prime, _ := new(big.Int).SetString( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"+ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"+ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"+ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"+ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"+ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + bad.Content.(*DGRound2Message1).NTilde = prime + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "prime NTildej", r4VictimIdx) +} + +func TestRound4RejectsPerfectSquareNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + p := fix.NewStates[r4VictimIdx].save.P + pp := new(big.Int).Mul(p, p) + if pp.BitLen() < 2048 { + q := fix.NewStates[r4VictimIdx].save.Q + pp = new(big.Int).Mul(q, q) + } + if pp.BitLen() < 2048 { + t.Skip("neither p*p nor q*q is >= 2048 bits; skipping") + } + bad.Content.(*DGRound2Message1).NTilde = pp + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "perfect-square NTildej", r4VictimIdx) +} + +func TestRound4RejectsPaillierNEqualsNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + content := bad.Content.(*DGRound2Message1) + content.NTilde = new(big.Int).Set(content.PaillierPK.N) + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "paillier N == NTilde", r4VictimIdx) +} + +func TestRound4RejectsH1NotCoprimeNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + content := bad.Content.(*DGRound2Message1) + // NTilde = (2P+1)(2Q+1). Set H1 = 2P+1 so gcd(H1, NTilde) != 1. + pPrep := fix.NewStates[r4VictimIdx].save.P + safeP := new(big.Int).Mul(pPrep, big.NewInt(2)) + safeP.Add(safeP, big.NewInt(1)) + content.H1 = safeP + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "h1j not coprime with NTildej", r4VictimIdx) +} + +func TestRound4RejectsH2NotCoprimeNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + bad := cloneDGRound2Message1(msgs[r4VictimIdx]) + content := bad.Content.(*DGRound2Message1) + // Same approach: set H2 to a factor of NTilde. + pPrep := fix.NewStates[r4VictimIdx].save.P + safeP := new(big.Int).Mul(pPrep, big.NewInt(2)) + safeP.Add(safeP, big.NewInt(1)) + content.H2 = safeP + msgs[r4VictimIdx] = bad + expectRound4ParamError(t, fix, msgs, "h2j not coprime with NTildej", r4VictimIdx) +} + +func TestRound4RejectsDuplicateH1(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Clone party 2's message and set its H1 to party 0's H1. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).H1 = new(big.Int).Set(party0Content.H1) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate h1j", 2) +} + +func TestRound4RejectsDuplicateH2(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Clone party 2's message and set its H2 to party 0's H2. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).H2 = new(big.Int).Set(party0Content.H2) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate h2j", 2) +} + +func TestRound4RejectsDuplicatePaillierN(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Clone party 2's message and set its PaillierPK.N to party 0's N. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).PaillierPK.N = new(big.Int).Set(party0Content.PaillierPK.N) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate modulus (paillier N)", 2) +} + +func TestRound4RejectsDuplicateNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Clone party 2's message and set its NTilde to party 0's NTilde. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).NTilde = new(big.Int).Set(party0Content.NTilde) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate modulus (NTilde)", 2) +} + +// TestRound4RejectsCrossDuplicateH1H2 verifies that the shared h1H2Map +// catches the case where party A's H1 equals party B's H2. +func TestRound4RejectsCrossDuplicateH1H2(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Set party 2's H1 to party 0's H2. Since party 0 is processed first, + // its H2 is already in the shared map when party 2's H1 is checked. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).H1 = new(big.Int).Set(party0Content.H2) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate h1j", 2) +} + +// TestRound4RejectsCrossPartyPaillierNEqualsNTilde verifies that the merged +// modulusMap catches cross-party collisions where Party A's PaillierN equals +// Party B's NTilde. +func TestRound4RejectsCrossPartyPaillierNEqualsNTilde(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Set party 2's PaillierPK.N to party 0's NTilde. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).PaillierPK.N = new(big.Int).Set(party0Content.NTilde) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate modulus (paillier N)", 2) +} + +// TestRound4RejectsCrossPartyNTildeEqualsPaillierN verifies the reverse +// direction: Party A's NTilde equals Party B's PaillierN. +func TestRound4RejectsCrossPartyNTildeEqualsPaillierN(t *testing.T) { + fix := setupThroughRound3(t) + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + // Set party 2's NTilde to party 0's PaillierN. + bad := cloneDGRound2Message1(msgs[2]) + party0Content := msgs[0].Content.(*DGRound2Message1) + bad.Content.(*DGRound2Message1).NTilde = new(big.Int).Set(party0Content.PaillierPK.N) + msgs[2] = bad + expectRound4ParamError(t, fix, msgs, "duplicate modulus (NTilde)", 2) +} diff --git a/tss-lib/ecdsa/resharing/round4_verify_negative_test.go b/tss-lib/ecdsa/resharing/round4_verify_negative_test.go new file mode 100644 index 0000000..bb35607 --- /dev/null +++ b/tss-lib/ecdsa/resharing/round4_verify_negative_test.go @@ -0,0 +1,257 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "context" + "crypto/rand" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestReshareRound4RejectsBadDecommitment corrupts the VDeCommitment from +// old party 0 and verifies that Round4 rejects it with a "v decommit failed" +// error. +func TestReshareRound4RejectsBadDecommitment(t *testing.T) { + fix := setupThroughRound3(t) + + const target = 0 // corrupt old party 0's decommitment + + // Build a corrupted r3Bcast: flip a value in the decommitment. + r3Bcast := copyR3BcastSlice(fix.OldR3Bcast) + orig := r3Bcast[target].Content.(*DGRound3Message2) + corruptD := make(cmt.HashDeCommitment, len(orig.VDeCommitment)) + for i, v := range orig.VDeCommitment { + if v != nil { + corruptD[i] = new(big.Int).Set(v) + } + } + // Corrupt the second element (first secret coordinate after randomness). + corruptD[1] = new(big.Int).Add(corruptD[1], big.NewInt(1)) + r3Bcast[target] = &tss.Message{ + From: r3Bcast[target].From, + To: r3Bcast[target].To, + IsBroadcast: true, + Content: &DGRound3Message2{VDeCommitment: corruptD}, + } + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], fix.NewR2Msg1s, fix.OldR3P2P[0], r3Bcast) + if err == nil { + t.Fatal("expected error from corrupted decommitment, got nil") + } + if !strings.Contains(err.Error(), "decommit") { + t.Fatalf("expected decommit error, got: %v", err) + } + requireCulprit(t, err, target) + t.Logf("correctly rejected bad decommitment: %v", err) +} + +// TestReshareRound4RejectsReceiverIDMismatch corrupts the ReceiverID in +// old party 1's P2P share message addressed to new party 0, and verifies +// that Round4 rejects it. +func TestReshareRound4RejectsReceiverIDMismatch(t *testing.T) { + fix := setupThroughRound3(t) + + const corruptFrom = 1 // corrupt message from old party 1 + + r3P2P := copyR3P2PSlice(fix.OldR3P2P[0]) + orig := r3P2P[corruptFrom].Content.(*DGRound3Message1) + // Replace ReceiverID with a garbage value. + r3P2P[corruptFrom] = &tss.Message{ + From: r3P2P[corruptFrom].From, + To: r3P2P[corruptFrom].To, + Content: &DGRound3Message1{ + Share: orig.Share, + ReceiverID: []byte("wrong-receiver-id"), + }, + } + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], fix.NewR2Msg1s, r3P2P, fix.OldR3Bcast) + if err == nil { + t.Fatal("expected error from ReceiverID mismatch, got nil") + } + if !strings.Contains(err.Error(), "receiverId mismatch") { + t.Fatalf("expected receiverId mismatch error, got: %v", err) + } + requireCulprit(t, err, corruptFrom) + t.Logf("correctly rejected ReceiverID mismatch: %v", err) +} + +// TestReshareRound4RejectsBadVSSShare corrupts the VSS share value from +// old party 2 and verifies that the Feldman VSS verification fails. +func TestReshareRound4RejectsBadVSSShare(t *testing.T) { + fix := setupThroughRound3(t) + + const corruptFrom = 2 // corrupt share from old party 2 + + r3P2P := copyR3P2PSlice(fix.OldR3P2P[0]) + orig := r3P2P[corruptFrom].Content.(*DGRound3Message1) + // Corrupt the share by adding 1. + badShare := new(big.Int).Add(orig.Share, big.NewInt(1)) + r3P2P[corruptFrom] = &tss.Message{ + From: r3P2P[corruptFrom].From, + To: r3P2P[corruptFrom].To, + Content: &DGRound3Message1{ + Share: badShare, + ReceiverID: orig.ReceiverID, + }, + } + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], fix.NewR2Msg1s, r3P2P, fix.OldR3Bcast) + if err == nil { + t.Fatal("expected error from corrupted VSS share, got nil") + } + if !strings.Contains(err.Error(), "vss share verify failed") { + t.Fatalf("expected vss share verify error, got: %v", err) + } + requireCulprit(t, err, corruptFrom) + t.Logf("correctly rejected bad VSS share: %v", err) +} + +// TestReshareRound4ContextCancellation passes a pre-cancelled context +// and verifies that Round4 returns an error (either context.Canceled +// or a wrapped form of it). +func TestReshareRound4ContextCancellation(t *testing.T) { + fix := setupThroughRound3(t) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() // pre-cancel + + _, err := ReshareRound4(ctx, fix.NewStates[0], fix.NewR2Msg1s, fix.OldR3P2P[0], fix.OldR3Bcast) + if err == nil { + t.Fatal("expected error from cancelled context, got nil") + } + if !strings.Contains(err.Error(), "cancel") && !strings.Contains(err.Error(), "context") { + t.Fatalf("expected context cancellation error, got: %v", err) + } + t.Logf("correctly rejected with cancelled context: %v", err) +} + +// TestReshareRound4RejectsNilModProof runs with ModProof enabled (not +// disabled via SetNoProofMod) and sets one new party's ModProof to nil. +// Exercises the proof-nil culprit path at round_fn.go:417-420. +func TestReshareRound4RejectsNilModProof(t *testing.T) { + fix := setupThroughRound3WithModProof(t) + + // Clone the R2 messages and nil out party 1's ModProof. + msgs := copyR2Msg1Slice(fix.NewR2Msg1s) + clone := cloneDGRound2Message1(msgs[r4VictimIdx]) + clone.Content.(*DGRound2Message1).ModProof = nil + msgs[r4VictimIdx] = clone + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], msgs, fix.OldR3P2P[0], fix.OldR3Bcast) + if err == nil { + t.Fatal("expected error for nil ModProof, got nil") + } + if !strings.Contains(err.Error(), "proof verification failed") { + t.Fatalf("expected 'proof verification failed', got: %v", err) + } + requireCulprit(t, err, r4VictimIdx) + t.Logf("correctly rejected nil ModProof: %v", err) +} + +// TestReshareRound4RejectsV0NotECDSAPub mutates the new party's stored +// ECDSAPub to a different valid curve point, so the reconstructed Vc[0] +// (sum of old parties' first VSS coefficients) does not match. All +// decommitments and VSS shares are legitimate — only the final +// comparison at round_fn.go:523 fails. +func TestReshareRound4RejectsV0NotECDSAPub(t *testing.T) { + fix := setupThroughRound3(t) + + // Create a different valid curve point (42·G on secp256k1). + fakeKey := crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) + if fakeKey.Equals(fix.NewStates[0].save.ECDSAPub) { + t.Fatal("precondition: fakeKey == real ECDSAPub") + } + fix.NewStates[0].save.ECDSAPub = fakeKey + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], fix.NewR2Msg1s, fix.OldR3P2P[0], fix.OldR3Bcast) + if err == nil { + t.Fatal("expected error from V_0 != ECDSAPub, got nil") + } + if !strings.Contains(err.Error(), "V_0 != ECDSAPub") { + t.Fatalf("expected 'V_0 != ECDSAPub' error, got: %v", err) + } + t.Logf("correctly rejected V_0 != ECDSAPub: %v", err) +} + +// TestReshareRound4RejectsWrongLengthDecommitment creates a valid +// commitment/decommitment pair (hash matches) with the wrong number of +// secrets. For threshold=1, Round4 expects (threshold+1)*2 = 4 values +// (two EC points flattened). This test provides 6, triggering the +// len(flatVs) branch at round_fn.go:482. +func TestReshareRound4RejectsWrongLengthDecommitment(t *testing.T) { + fix := setupThroughRound3(t) + + const target = 0 + + // 6 secrets instead of 4 → len(flatVs) == 6, expected 4. + wrongCmt := cmt.NewHashCommitment(rand.Reader, + big.NewInt(1), big.NewInt(2), big.NewInt(3), + big.NewInt(4), big.NewInt(5), big.NewInt(6)) + + // Patch the stored R1 commitment hash. + fix.NewStates[0].temp.dgRound1Messages[target].Content.(*DGRound1Message).VCommitment = wrongCmt.C + + // Patch the R3 broadcast decommitment. + r3Bcast := copyR3BcastSlice(fix.OldR3Bcast) + r3Bcast[target] = &tss.Message{ + From: fix.OldR3Bcast[target].From, + To: fix.OldR3Bcast[target].To, + IsBroadcast: true, + Content: &DGRound3Message2{VDeCommitment: wrongCmt.D}, + } + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], fix.NewR2Msg1s, fix.OldR3P2P[0], r3Bcast) + if err == nil { + t.Fatal("expected error from wrong-length decommitment, got nil") + } + if !strings.Contains(err.Error(), "decommit") { + t.Fatalf("expected decommit error, got: %v", err) + } + requireCulprit(t, err, target) + t.Logf("correctly rejected wrong-length decommitment: %v", err) +} + +// TestReshareRound4RejectsOffCurveDecommitment creates a valid +// commitment/decommitment pair with the correct number of secrets (4) +// but where the coordinate pairs (1,1) and (2,2) are not on secp256k1. +// Exercises the UnFlattenECPoints error at round_fn.go:485-488. +func TestReshareRound4RejectsOffCurveDecommitment(t *testing.T) { + fix := setupThroughRound3(t) + + const target = 0 + + // (1,1) and (2,2) are not on secp256k1 (y^2 != x^3 + 7 mod p). + offCmt := cmt.NewHashCommitment(rand.Reader, + big.NewInt(1), big.NewInt(1), big.NewInt(2), big.NewInt(2)) + + // Patch the stored R1 commitment hash. + fix.NewStates[0].temp.dgRound1Messages[target].Content.(*DGRound1Message).VCommitment = offCmt.C + + // Patch the R3 broadcast decommitment. + r3Bcast := copyR3BcastSlice(fix.OldR3Bcast) + r3Bcast[target] = &tss.Message{ + From: fix.OldR3Bcast[target].From, + To: fix.OldR3Bcast[target].To, + IsBroadcast: true, + Content: &DGRound3Message2{VDeCommitment: offCmt.D}, + } + + _, err := ReshareRound4(context.Background(), fix.NewStates[0], fix.NewR2Msg1s, fix.OldR3P2P[0], r3Bcast) + if err == nil { + t.Fatal("expected error from off-curve decommitment, got nil") + } + if !strings.Contains(err.Error(), "not on the elliptic curve") { + t.Fatalf("expected curve error, got: %v", err) + } + requireCulprit(t, err, target) + t.Logf("correctly rejected off-curve decommitment: %v", err) +} diff --git a/tss-lib/ecdsa/resharing/round_1_old_step_1.go b/tss-lib/ecdsa/resharing/round_1_old_step_1.go deleted file mode 100644 index 6b598d3..0000000 --- a/tss-lib/ecdsa/resharing/round_1_old_step_1.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/signing" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// round 1 represents round 1 of the keygen part of the GG18 ECDSA TSS spec (Gennaro, Goldfeder; 2018) -func newRound1(params *tss.ReSharingParameters, input, save *keygen.LocalPartySaveData, temp *localTempData, out chan<- tss.Message, end chan<- *keygen.LocalPartySaveData) tss.Round { - return &round1{ - &base{params, temp, input, save, out, end, make([]bool, len(params.OldParties().IDs())), make([]bool, len(params.NewParties().IDs())), false, 1}, - } -} - -func (round *round1) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 1 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - round.allNewOK() - - if !round.ReSharingParams().IsOldCommittee() { - return nil - } - round.allOldOK() - - round.temp.ssidNonce = new(big.Int).SetUint64(uint64(0)) - ssid, err := round.getSSID() - if err != nil { - return round.WrapError(err) - } - round.temp.ssid = ssid - Pi := round.PartyID() - i := Pi.Index - - // 1. PrepareForSigning() -> w_i - xi, ks, bigXj := round.input.Xi, round.input.Ks, round.input.BigXj - if round.Threshold()+1 > len(ks) { - return round.WrapError(fmt.Errorf("t+1=%d is not satisfied by the key count of %d", round.Threshold()+1, len(ks)), round.PartyID()) - } - newKs := round.NewParties().IDs().Keys() - wi, _ := signing.PrepareForSigning(round.Params().EC(), i, len(round.OldParties().IDs()), xi, ks, bigXj) - - // 2. - vi, shares, err := vss.Create(round.Params().EC(), round.NewThreshold(), wi, newKs, round.Rand()) - if err != nil { - return round.WrapError(err, round.PartyID()) - } - - // 3. - flatVis, err := crypto.FlattenECPoints(vi) - if err != nil { - return round.WrapError(err, round.PartyID()) - } - vCmt := commitments.NewHashCommitment(round.Rand(), flatVis...) - - // 4. populate temp data - round.temp.VD = vCmt.D - round.temp.NewShares = shares - - // 5. "broadcast" C_i to members of the NEW committee - r1msg := NewDGRound1Message( - round.NewParties().IDs().Exclude(round.PartyID()), round.PartyID(), - round.input.ECDSAPub, vCmt.C, ssid) - round.temp.dgRound1Messages[i] = r1msg - round.out <- r1msg - - return nil -} - -func (round *round1) CanAccept(msg tss.ParsedMessage) bool { - // accept messages from old -> new committee - if _, ok := msg.Content().(*DGRound1Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round1) Update() (bool, *tss.Error) { - // only the new committee receive in this round - if !round.ReSharingParameters.IsNewCommittee() { - return true, nil - } - // accept messages from old -> new committee - ret := true - for j, msg := range round.temp.dgRound1Messages { - if round.oldOK[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.oldOK[j] = true - - // save the ecdsa pub received from the old committee - if round.temp.dgRound1Messages[0] == nil { - ret = false - continue - } - r1msg := round.temp.dgRound1Messages[0].Content().(*DGRound1Message) - candidate, err := r1msg.UnmarshalECDSAPub(round.Params().EC()) - if err != nil { - return false, round.WrapError(errors.New("unable to unmarshal the ecdsa pub key"), msg.GetFrom()) - } - if round.save.ECDSAPub != nil && - !candidate.Equals(round.save.ECDSAPub) { - // uh oh - anomaly! - return false, round.WrapError(errors.New("ecdsa pub key did not match what we received previously"), msg.GetFrom()) - } - round.save.ECDSAPub = candidate - } - return ret, nil -} - -func (round *round1) NextRound() tss.Round { - round.started = false - return &round2{round} -} diff --git a/tss-lib/ecdsa/resharing/round_2_new_step_1.go b/tss-lib/ecdsa/resharing/round_2_new_step_1.go deleted file mode 100644 index a94e881..0000000 --- a/tss-lib/ecdsa/resharing/round_2_new_step_1.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "bytes" - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/crypto/modproof" - - "github.com/hemilabs/x/tss-lib/v2/crypto/dlnproof" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -var zero = big.NewInt(0) - -func (round *round2) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 2 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - round.allOldOK() - - if !round.ReSharingParams().IsNewCommittee() { - return nil - } - - Pi := round.PartyID() - i := Pi.Index - - // check consistency of SSID - r1msg := round.temp.dgRound1Messages[0].Content().(*DGRound1Message) - SSID := r1msg.UnmarshalSSID() - for j, Pj := range round.OldParties().IDs() { - if j == 0 || j == i { - continue - } - r1msg := round.temp.dgRound1Messages[j].Content().(*DGRound1Message) - SSIDj := r1msg.UnmarshalSSID() - if !bytes.Equal(SSID, SSIDj) { - return round.WrapError(errors.New("ssid mismatch"), Pj) - } - } - round.temp.ssid = SSID - - // 2. "broadcast" "ACK" members of the OLD committee - r2msg1 := NewDGRound2Message2( - round.OldParties().IDs().Exclude(round.PartyID()), round.PartyID()) - round.temp.dgRound2Message2s[i] = r2msg1 - round.out <- r2msg1 - - // 1. - // generate Paillier public key E_i, private key and proof - // generate safe primes for ZKPs later on - // compute ntilde, h1, h2 (uses safe primes) - // use the pre-params if they were provided to the LocalParty constructor - var preParams *keygen.LocalPreParams - if round.save.LocalPreParams.Validate() && !round.save.LocalPreParams.ValidateWithProof() { - return round.WrapError( - errors.New("`optionalPreParams` failed to validate; it might have been generated with an older version of tss-lib")) - } else if round.save.LocalPreParams.ValidateWithProof() { - preParams = &round.save.LocalPreParams - } else { - var err error - preParams, err = keygen.GeneratePreParams(round.SafePrimeGenTimeout(), round.Concurrency()) - if err != nil { - return round.WrapError(errors.New("pre-params generation failed"), Pi) - } - } - round.save.LocalPreParams = *preParams - round.save.NTildej[i] = preParams.NTildei - round.save.H1j[i], round.save.H2j[i] = preParams.H1i, preParams.H2i - - // generate the dlnproofs for resharing - h1i, h2i, alpha, beta, p, q, NTildei := preParams.H1i, - preParams.H2i, - preParams.Alpha, - preParams.Beta, - preParams.P, - preParams.Q, - preParams.NTildei - dlnProof1 := dlnproof.NewDLNProof(h1i, h2i, alpha, p, q, NTildei, round.Rand()) - dlnProof2 := dlnproof.NewDLNProof(h2i, h1i, beta, p, q, NTildei, round.Rand()) - - modProof := &modproof.ProofMod{W: zero, X: *new([80]*big.Int), A: zero, B: zero, Z: *new([80]*big.Int)} - ContextI := append(round.temp.ssid, big.NewInt(int64(i)).Bytes()...) - if !round.Parameters.NoProofMod() { - var err error - modProof, err = modproof.NewProof(ContextI, preParams.PaillierSK.N, preParams.PaillierSK.P, preParams.PaillierSK.Q, round.Rand()) - if err != nil { - return round.WrapError(err, Pi) - } - } - r2msg2, err := NewDGRound2Message1( - round.NewParties().IDs().Exclude(round.PartyID()), round.PartyID(), - &preParams.PaillierSK.PublicKey, modProof, preParams.NTildei, preParams.H1i, preParams.H2i, dlnProof1, dlnProof2) - if err != nil { - return round.WrapError(err, Pi) - } - round.temp.dgRound2Message1s[i] = r2msg2 - round.out <- r2msg2 - - // for this P: SAVE de-commitments, paillier keys for round 2 - round.save.PaillierSK = preParams.PaillierSK - round.save.PaillierPKs[i] = &preParams.PaillierSK.PublicKey - round.save.NTildej[i] = preParams.NTildei - round.save.H1j[i], round.save.H2j[i] = preParams.H1i, preParams.H2i - - return nil -} - -func (round *round2) CanAccept(msg tss.ParsedMessage) bool { - if round.ReSharingParams().IsNewCommittee() { - if _, ok := msg.Content().(*DGRound2Message1); ok { - return msg.IsBroadcast() - } - } - if round.ReSharingParams().IsOldCommittee() { - if _, ok := msg.Content().(*DGRound2Message2); ok { - return msg.IsBroadcast() - } - } - return false -} - -func (round *round2) Update() (bool, *tss.Error) { - ret := true - if round.ReSharingParams().IsOldCommittee() && round.ReSharingParameters.IsNewCommittee() { - // accept messages from new -> old committee - for j, msg1 := range round.temp.dgRound2Message2s { - if round.newOK[j] { - continue - } - if msg1 == nil || !round.CanAccept(msg1) { - ret = false - continue - } - // accept message from new -> committee - msg2 := round.temp.dgRound2Message1s[j] - if msg2 == nil || !round.CanAccept(msg2) { - ret = false - continue - } - round.newOK[j] = true - } - } else if round.ReSharingParams().IsOldCommittee() { - // accept messages from new -> old committee - for j, msg := range round.temp.dgRound2Message2s { - if round.newOK[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.newOK[j] = true - } - } else if round.ReSharingParams().IsNewCommittee() { - // accept messages from new -> new committee - for j, msg := range round.temp.dgRound2Message1s { - if round.newOK[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.newOK[j] = true - } - } else { - return false, round.WrapError(errors.New("this party is not in the old or the new committee"), round.PartyID()) - } - return ret, nil -} - -func (round *round2) NextRound() tss.Round { - round.started = false - return &round3{round} -} diff --git a/tss-lib/ecdsa/resharing/round_3_old_step_2.go b/tss-lib/ecdsa/resharing/round_3_old_step_2.go deleted file mode 100644 index 6e51d0e..0000000 --- a/tss-lib/ecdsa/resharing/round_3_old_step_2.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round3) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 3 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - round.allNewOK() - - if !round.ReSharingParams().IsOldCommittee() { - return nil - } - round.allOldOK() - - Pi := round.PartyID() - i := Pi.Index - - // 2. send share to Pj from the new committee - for j, Pj := range round.NewParties().IDs() { - share := round.temp.NewShares[j] - r3msg1 := NewDGRound3Message1(Pj, round.PartyID(), share) - round.temp.dgRound3Message1s[i] = r3msg1 - round.out <- r3msg1 - } - - vDeCmt := round.temp.VD - r3msg2 := NewDGRound3Message2( - round.NewParties().IDs().Exclude(round.PartyID()), round.PartyID(), - vDeCmt) - round.temp.dgRound3Message2s[i] = r3msg2 - round.out <- r3msg2 - - return nil -} - -func (round *round3) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*DGRound3Message1); ok { - return !msg.IsBroadcast() - } - if _, ok := msg.Content().(*DGRound3Message2); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round3) Update() (bool, *tss.Error) { - // only the new committee receive in this round - if !round.ReSharingParams().IsNewCommittee() { - return true, nil - } - // accept messages from old -> new committee - for j, msg1 := range round.temp.dgRound3Message1s { - if round.oldOK[j] { - continue - } - if msg1 == nil || !round.CanAccept(msg1) { - return false, nil - } - msg2 := round.temp.dgRound3Message2s[j] - if msg2 == nil || !round.CanAccept(msg2) { - return false, nil - } - round.oldOK[j] = true - } - return true, nil -} - -func (round *round3) NextRound() tss.Round { - round.started = false - return &round4{round} -} diff --git a/tss-lib/ecdsa/resharing/round_4_new_step_2.go b/tss-lib/ecdsa/resharing/round_4_new_step_2.go deleted file mode 100644 index 4ee87dd..0000000 --- a/tss-lib/ecdsa/resharing/round_4_new_step_2.go +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "encoding/hex" - "errors" - "math/big" - "sync" - - "github.com/hemilabs/x/tss-lib/v2/crypto/facproof" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round4) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 4 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - - round.allOldOK() - - if !round.ReSharingParams().IsNewCommittee() { - // both committees proceed to round 5 after receiving "ACK" messages from the new committee - return nil - } - - common.Logger.Debugf( - "%s Setting up DLN verification with concurrency level of %d", - round.PartyID(), - round.Concurrency(), - ) - dlnVerifier := keygen.NewDlnProofVerifier(round.Concurrency()) - - Pi := round.PartyID() - i := Pi.Index - round.newOK[i] = true - - // 1-3. verify paillier & dln proofs, store message pieces, ensure uniqueness of h1j, h2j - h1H2Map := make(map[string]struct{}, len(round.temp.dgRound2Message1s)*2) - paiProofCulprits := make([]*tss.PartyID, len(round.temp.dgRound2Message1s)) // who caused the error(s) - dlnProof1FailCulprits := make([]*tss.PartyID, len(round.temp.dgRound2Message1s)) - dlnProof2FailCulprits := make([]*tss.PartyID, len(round.temp.dgRound2Message1s)) - wg := new(sync.WaitGroup) - for j, msg := range round.temp.dgRound2Message1s { - r2msg1 := msg.Content().(*DGRound2Message1) - paiPK, NTildej, H1j, H2j := r2msg1.UnmarshalPaillierPK(), - r2msg1.UnmarshalNTilde(), - r2msg1.UnmarshalH1(), - r2msg1.UnmarshalH2() - if H1j.Cmp(H2j) == 0 { - return round.WrapError(errors.New("h1j and h2j were equal for this party"), msg.GetFrom()) - } - h1JHex, h2JHex := hex.EncodeToString(H1j.Bytes()), hex.EncodeToString(H2j.Bytes()) - if _, found := h1H2Map[h1JHex]; found { - return round.WrapError(errors.New("this h1j was already used by another party"), msg.GetFrom()) - } - if _, found := h1H2Map[h2JHex]; found { - return round.WrapError(errors.New("this h2j was already used by another party"), msg.GetFrom()) - } - h1H2Map[h1JHex], h1H2Map[h2JHex] = struct{}{}, struct{}{} - wg.Add(3) - go func(j int, msg tss.ParsedMessage, r2msg1 *DGRound2Message1) { - defer wg.Done() - modProof, err := r2msg1.UnmarshalModProof() - if err != nil { - if !round.Parameters.NoProofMod() { - paiProofCulprits[j] = msg.GetFrom() - } - common.Logger.Warningf("modProof verify failed for party %s", msg.GetFrom(), err) - return - } - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - if ok := modProof.Verify(ContextJ, paiPK.N); !ok { - paiProofCulprits[j] = msg.GetFrom() - common.Logger.Warningf("modProof verify failed for party %s", msg.GetFrom(), err) - } - }(j, msg, r2msg1) - _j := j - _msg := msg - dlnVerifier.VerifyDLNProof1(r2msg1, H1j, H2j, NTildej, func(isValid bool) { - if !isValid { - dlnProof1FailCulprits[_j] = _msg.GetFrom() - common.Logger.Warningf("dln proof 1 verify failed for party %s", _msg.GetFrom()) - } - wg.Done() - }) - dlnVerifier.VerifyDLNProof2(r2msg1, H2j, H1j, NTildej, func(isValid bool) { - if !isValid { - dlnProof2FailCulprits[_j] = _msg.GetFrom() - common.Logger.Warningf("dln proof 2 verify failed for party %s", _msg.GetFrom()) - } - wg.Done() - }) - } - wg.Wait() - for _, culprit := range append(append(paiProofCulprits, dlnProof1FailCulprits...), dlnProof2FailCulprits...) { - if culprit != nil { - return round.WrapError(errors.New("dln proof verification failed"), culprit) - } - } - // save NTilde_j, h1_j, h2_j received in NewCommitteeStep1 here - for j, msg := range round.temp.dgRound2Message1s { - if j == i { - continue - } - r2msg1 := msg.Content().(*DGRound2Message1) - round.save.NTildej[j] = new(big.Int).SetBytes(r2msg1.NTilde) - round.save.H1j[j] = new(big.Int).SetBytes(r2msg1.H1) - round.save.H2j[j] = new(big.Int).SetBytes(r2msg1.H2) - } - - // 4. - newXi := big.NewInt(0) - - // 5-9. - modQ := common.ModInt(round.Params().EC().Params().N) - vjc := make([][]*crypto.ECPoint, len(round.OldParties().IDs())) - for j := 0; j <= len(vjc)-1; j++ { // P1..P_t+1. Ps are indexed from 0 here - // 6-7. - r1msg := round.temp.dgRound1Messages[j].Content().(*DGRound1Message) - r3msg2 := round.temp.dgRound3Message2s[j].Content().(*DGRound3Message2) - - vCj, vDj := r1msg.UnmarshalVCommitment(), r3msg2.UnmarshalVDeCommitment() - - // 6. unpack flat "v" commitment content - vCmtDeCmt := commitments.HashCommitDecommit{C: vCj, D: vDj} - ok, flatVs := vCmtDeCmt.DeCommit() - if !ok || len(flatVs) != (round.NewThreshold()+1)*2 { // they're points so * 2 - // TODO collect culprits and return a list of them as per convention - return round.WrapError(errors.New("de-commitment of v_j0..v_jt failed"), round.Parties().IDs()[j]) - } - vj, err := crypto.UnFlattenECPoints(round.Params().EC(), flatVs) - if err != nil { - return round.WrapError(err, round.Parties().IDs()[j]) - } - vjc[j] = vj - - // 8. - r3msg1 := round.temp.dgRound3Message1s[j].Content().(*DGRound3Message1) - sharej := &vss.Share{ - Threshold: round.NewThreshold(), - ID: round.PartyID().KeyInt(), - Share: new(big.Int).SetBytes(r3msg1.Share), - } - if ok := sharej.Verify(round.Params().EC(), round.NewThreshold(), vj); !ok { - // TODO collect culprits and return a list of them as per convention - return round.WrapError(errors.New("share from old committee did not pass Verify()"), round.Parties().IDs()[j]) - } - - // 9. - newXi = new(big.Int).Add(newXi, sharej.Share) - } - - // 10-13. - var err error - Vc := make([]*crypto.ECPoint, round.NewThreshold()+1) - for c := 0; c <= round.NewThreshold(); c++ { - Vc[c] = vjc[0][c] - for j := 1; j <= len(vjc)-1; j++ { - Vc[c], err = Vc[c].Add(vjc[j][c]) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "Vc[c].Add(vjc[j][c])")) - } - } - } - - // 14. - if !Vc[0].Equals(round.save.ECDSAPub) { - return round.WrapError(errors.New("assertion failed: V_0 != y"), round.PartyID()) - } - - // 15-19. - newKs := make([]*big.Int, 0, round.NewPartyCount()) - newBigXjs := make([]*crypto.ECPoint, round.NewPartyCount()) - paiProofCulprits = make([]*tss.PartyID, 0, round.NewPartyCount()) // who caused the error(s) - for j := 0; j < round.NewPartyCount(); j++ { - Pj := round.NewParties().IDs()[j] - kj := Pj.KeyInt() - newBigXj := Vc[0] - newKs = append(newKs, kj) - z := new(big.Int).SetInt64(int64(1)) - for c := 1; c <= round.NewThreshold(); c++ { - z = modQ.Mul(z, kj) - newBigXj, err = newBigXj.Add(Vc[c].ScalarMult(z)) - if err != nil { - paiProofCulprits = append(paiProofCulprits, Pj) - } - } - newBigXjs[j] = newBigXj - } - if len(paiProofCulprits) > 0 { - return round.WrapError(errors2.Wrapf(err, "newBigXj.Add(Vc[c].ScalarMult(z))"), paiProofCulprits...) - } - - round.temp.newXi = newXi - round.temp.newKs = newKs - round.temp.newBigXjs = newBigXjs - - // Send facProof to new parties - for j, Pj := range round.NewParties().IDs() { - if j == i { - continue - } - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - facProof := &facproof.ProofFac{ - P: zero, Q: zero, A: zero, B: zero, T: zero, Sigma: zero, - Z1: zero, Z2: zero, W1: zero, W2: zero, V: zero, - } - if !round.Parameters.NoProofFac() { - facProof, err = facproof.NewProof(ContextJ, round.EC(), round.save.PaillierSK.N, round.save.NTildej[j], - round.save.H1j[j], round.save.H2j[j], round.save.PaillierSK.P, round.save.PaillierSK.Q, round.Rand()) - if err != nil { - return round.WrapError(err, Pi) - } - } - r4msg1 := NewDGRound4Message1(Pj, Pi, facProof) - round.out <- r4msg1 - } - - // Send an "ACK" message to both committees to signal that we're ready to save our data - r4msg2 := NewDGRound4Message2(round.OldAndNewParties(), Pi) - round.temp.dgRound4Message2s[i] = r4msg2 - round.out <- r4msg2 - - return nil -} - -func (round *round4) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*DGRound4Message1); ok { - return !msg.IsBroadcast() - } - if _, ok := msg.Content().(*DGRound4Message2); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round4) Update() (bool, *tss.Error) { - // accept messages from new -> old&new committees - for j, msg2 := range round.temp.dgRound4Message2s { - if round.newOK[j] { - continue - } - if msg2 == nil || !round.CanAccept(msg2) { - return false, nil - } - if round.ReSharingParams().IsNewCommittee() { - msg1 := round.temp.dgRound4Message1s[j] - if msg1 == nil || !round.CanAccept(msg1) { - return false, nil - } - } - round.newOK[j] = true - } - return true, nil -} - -func (round *round4) NextRound() tss.Round { - round.started = false - return &round5{round} -} diff --git a/tss-lib/ecdsa/resharing/round_5_new_step_3.go b/tss-lib/ecdsa/resharing/round_5_new_step_3.go deleted file mode 100644 index 9486b4d..0000000 --- a/tss-lib/ecdsa/resharing/round_5_new_step_3.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round5) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 5 - round.started = true - - round.allOldOK() - round.allNewOK() - - Pi := round.PartyID() - i := Pi.Index - - if round.IsNewCommittee() { - // 21. - // for this P: SAVE data - ContextI := append(round.temp.ssid, big.NewInt(int64(i)).Bytes()...) - round.save.BigXj = round.temp.newBigXjs - round.save.ShareID = round.PartyID().KeyInt() - round.save.Xi = round.temp.newXi - round.save.Ks = round.temp.newKs - - // misc: build list of paillier public keys to save - for j, msg := range round.temp.dgRound2Message1s { - if j == i { - continue - } - r2msg1 := msg.Content().(*DGRound2Message1) - round.save.PaillierPKs[j] = r2msg1.UnmarshalPaillierPK() - } - for j, msg := range round.temp.dgRound4Message1s { - if j == i { - continue - } - r4msg1 := msg.Content().(*DGRound4Message1) - proof, err := r4msg1.UnmarshalFacProof() - if err != nil && round.Parameters.NoProofFac() { - common.Logger.Warningf("facProof verify failed for party %s", msg.GetFrom(), err) - } else { - if err != nil { - common.Logger.Warningf("facProof verify failed for party %s", msg.GetFrom(), err) - return round.WrapError(err, round.NewParties().IDs()[j]) - } - if ok := proof.Verify(ContextI, round.EC(), round.save.PaillierPKs[j].N, round.save.NTildei, - round.save.H1i, round.save.H2i); !ok { - common.Logger.Warningf("facProof verify failed for party %s", msg.GetFrom(), err) - return round.WrapError(err, round.NewParties().IDs()[j]) - } - } - - } - } else if round.IsOldCommittee() { - round.input.Xi.SetInt64(0) - } - - round.end <- round.save - return nil -} - -func (round *round5) CanAccept(msg tss.ParsedMessage) bool { - return false -} - -func (round *round5) Update() (bool, *tss.Error) { - return false, nil -} - -func (round *round5) NextRound() tss.Round { - return nil // both committees are finished! -} diff --git a/tss-lib/ecdsa/resharing/round_fn.go b/tss-lib/ecdsa/resharing/round_fn.go new file mode 100644 index 0000000..54788da --- /dev/null +++ b/tss-lib/ecdsa/resharing/round_fn.go @@ -0,0 +1,638 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "math/big" + "sync" + + errors2 "github.com/pkg/errors" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +var ( + reshareOne = big.NewInt(1) + resharePaiBitsLen = 2048 +) + +// oldIndex returns this party's index in the old committee, or -1. +func oldIndex(params *tss.ReSharingParameters) int { + key := params.PartyID().KeyInt() + for i, pid := range params.OldParties().IDs() { + if pid.KeyInt().Cmp(key) == 0 { + return i + } + } + return -1 +} + +// newIndex returns this party's index in the new committee, or -1. +func newIndex(params *tss.ReSharingParameters) int { + key := params.PartyID().KeyInt() + for i, pid := range params.NewParties().IDs() { + if pid.KeyInt().Cmp(key) == 0 { + return i + } + } + return -1 +} + +func getReshareSSID(params *tss.ReSharingParameters, input *keygen.LocalPartySaveData, temp *localTempData, roundNumber int) ([]byte, error) { + ssidList := []*big.Int{ + new(big.Int).SetBytes([]byte("ecdsa-resharing")), + params.EC().Params().P, params.EC().Params().N, + params.EC().Params().B, params.EC().Params().Gx, + params.EC().Params().Gy, + } + ssidList = append(ssidList, params.OldParties().IDs().Keys()...) + ssidList = append(ssidList, params.NewParties().IDs().Keys()...) + BigXjList, err := crypto.FlattenECPoints(input.BigXj) + if err != nil { + return nil, fmt.Errorf("flatten ec points: %w", err) + } + ssidList = append(ssidList, BigXjList...) + ssidList = append(ssidList, input.NTildej...) + ssidList = append(ssidList, input.H1j...) + ssidList = append(ssidList, input.H2j...) + ssidList = append(ssidList, big.NewInt(int64(params.PartyCount()))) + ssidList = append(ssidList, big.NewInt(int64(params.Threshold()))) + ssidList = append(ssidList, big.NewInt(int64(params.NewPartyCount()))) + ssidList = append(ssidList, big.NewInt(int64(params.NewThreshold()))) + ssidList = append(ssidList, big.NewInt(int64(roundNumber))) + ssidList = append(ssidList, temp.ssidNonce) + if cid := params.CeremonyID(); len(cid) > 0 { + ssidList = append(ssidList, new(big.Int).SetBytes(cid)) + } + return common.SHA512_256i(ssidList...).Bytes(), nil +} + +// ReshareRound1 creates a new ReshareState and produces the round 1 +// broadcast message. Only old committee members produce output. +// +// key is the existing key share. preParams is for the new committee +// (may be zero-value if this party is old-only). +func ReshareRound1(params *tss.ReSharingParameters, key keygen.LocalPartySaveData, preParams keygen.LocalPreParams) (*ReshareState, *ReshareRoundOutput, error) { + oldPC := params.OldPartyCount() + newPC := params.NewPartyCount() + input := key + if params.IsOldCommittee() { + input = keygen.BuildLocalSaveDataSubset(key, params.OldParties().IDs()) + } + save := keygen.NewLocalPartySaveData(newPC) + if preParams.ValidateWithProof() { + save.LocalPreParams = preParams + } + + temp := &localTempData{ + localMessageStore: localMessageStore{ + dgRound1Messages: make([]*tss.Message, oldPC), + dgRound2Message1s: make([]*tss.Message, newPC), + dgRound2Message2s: make([]*tss.Message, newPC), + dgRound3Message1s: make([]*tss.Message, oldPC), + dgRound3Message2s: make([]*tss.Message, oldPC), + dgRound4Message1s: make([]*tss.Message, newPC), + dgRound4Message2s: make([]*tss.Message, newPC), + }, + } + + state := &ReshareState{params: params, input: &input, save: &save, temp: temp} + out := &ReshareRoundOutput{} + + if !params.IsOldCommittee() { + return state, out, nil + } + + temp.ssidNonce = new(big.Int).SetUint64(uint64(params.SSIDNonce())) + ssid, err := getReshareSSID(params, &input, temp, 1) + if err != nil { + return nil, nil, err + } + temp.ssid = ssid + + Pi := params.PartyID() + i := oldIndex(params) + xi, ks, bigXj := input.Xi, input.Ks, input.BigXj + if params.Threshold()+1 > len(ks) { + return nil, nil, fmt.Errorf("t+1=%d > key count %d", params.Threshold()+1, len(ks)) + } + newKs := params.NewParties().IDs().Keys() + wi, _ := signing.PrepareForSigning(params.EC(), i, len(params.OldParties().IDs()), xi, ks, bigXj) + + vi, shares, poly, err := vss.Create(params.EC(), params.NewThreshold(), wi, newKs, params.Rand()) + if err != nil { + return nil, nil, err + } + + flatVis, err := crypto.FlattenECPoints(vi) + if err != nil { + return nil, nil, err + } + vCmt := commitments.NewHashCommitment(params.Rand(), flatVis...) + + temp.VD = vCmt.D + temp.NewShares = shares + temp.NewVs = vi + temp.Poly = poly + + r1msg := NewDGRound1Message( + params.NewParties().IDs().Exclude(Pi), Pi, + input.ECDSAPub, vCmt.C, ssid) + temp.dgRound1Messages[i] = r1msg + out.Messages = append(out.Messages, r1msg) + out.Poly = poly + out.NewVs = vi + + return state, out, nil +} + +// ReshareRound2 processes round 1 messages from the old committee and +// produces Pedersen parameters + proofs for the new committee. +// +// r1Msgs are DGRound1Message broadcasts from old committee. +// Only new committee members produce output. +func ReshareRound2(state *ReshareState, r1Msgs []*tss.Message) (*ReshareRoundOutput, error) { + params, save, temp := state.params, state.save, state.temp + tss.MergeMsgs(temp.dgRound1Messages, r1Msgs) + out := &ReshareRoundOutput{} + + if !params.IsNewCommittee() { + return out, nil + } + + Pi := params.PartyID() + i := newIndex(params) + + // Validate SSID consistency across old committee + r1msg0 := r1Msgs[0].Content.(*DGRound1Message) + SSID := r1msg0.SSID + for j := range params.OldParties().IDs() { + if j == 0 { + continue + } + r1msg := r1Msgs[j].Content.(*DGRound1Message) + SSIDj := r1msg.SSID + if !bytes.Equal(SSID, SSIDj) { + return nil, tss.NewError(errors.New("ssid mismatch"), TaskName, 2, Pi, params.OldParties().IDs()[j]) + } + } + temp.ssid = SSID + + // Save ECDSAPub from old committee + for j := range params.OldParties().IDs() { + r1msg := r1Msgs[j].Content.(*DGRound1Message) + candidate := r1msg.ECDSAPub + if candidate == nil { + return nil, fmt.Errorf("round 2: ecdsa pub nil from party %d", j) + } + if save.ECDSAPub != nil && !candidate.Equals(save.ECDSAPub) { + return nil, errors.New("ecdsa pub key mismatch from old committee") + } + save.ECDSAPub = candidate + } + + // ACK to old committee + r2msg1 := NewDGRound2Message2( + params.OldParties().IDs().Exclude(Pi), Pi) + temp.dgRound2Message2s[i] = r2msg1 + out.Messages = append(out.Messages, r2msg1) + + // Generate pre-params if not provided + var preParams *keygen.LocalPreParams + if save.Validate() && !save.ValidateWithProof() { + return nil, errors.New("preParams failed validation") + } else if save.ValidateWithProof() { + preParams = &save.LocalPreParams + } else { + var err error + preParams, err = keygen.GeneratePreParams(params.SafePrimeGenTimeout(), params.Concurrency()) + if err != nil { + return nil, errors.New("pre-params generation failed") + } + } + save.LocalPreParams = *preParams + save.NTildej[i] = preParams.NTildei + save.H1j[i], save.H2j[i] = preParams.H1i, preParams.H2i + + h1i, h2i, alpha, beta := preParams.H1i, preParams.H2i, preParams.Alpha, preParams.Beta + p, q, NTildei := preParams.P, preParams.Q, preParams.NTildei + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(i))) + + var dlnProof1, dlnProof2 *dlnproof.Proof + if !params.NoProofDLN() { + dlnProof1 = dlnproof.NewDLNProof(ContextI, h1i, h2i, alpha, p, q, NTildei, params.Rand()) + dlnProof2 = dlnproof.NewDLNProof(ContextI, h2i, h1i, beta, p, q, NTildei, params.Rand()) + } + + var modProofObj *modproof.ProofMod + if !params.NoProofMod() { + var err error + modProofObj, err = modproof.NewProof(ContextI, preParams.PaillierSK.N, + preParams.PaillierSK.P, preParams.PaillierSK.Q, params.Rand()) + if err != nil { + return nil, fmt.Errorf("round 2 mod proof: %w", err) + } + } + + r2msg2 := NewDGRound2Message1( + params.NewParties().IDs().Exclude(Pi), Pi, + &preParams.PaillierSK.PublicKey, modProofObj, + preParams.NTildei, preParams.H1i, preParams.H2i, + dlnProof1, dlnProof2) + temp.dgRound2Message1s[i] = r2msg2 + out.Messages = append(out.Messages, r2msg2) + + save.PaillierSK = preParams.PaillierSK + save.PaillierPKs[i] = &preParams.PaillierSK.PublicKey + + return out, nil +} + +// ReshareRound3 sends VSS shares to new committee members. +// Only old committee members produce output. +// +// r2AckMsgs are DGRound2Message2 broadcasts from new committee. +func ReshareRound3(state *ReshareState, r2AckMsgs []*tss.Message) (*ReshareRoundOutput, error) { + params, temp := state.params, state.temp + tss.MergeMsgs(temp.dgRound2Message2s, r2AckMsgs) + out := &ReshareRoundOutput{} + + if !params.IsOldCommittee() { + return out, nil + } + + Pi := params.PartyID() + i := oldIndex(params) + + for j, Pj := range params.NewParties().IDs() { + share := temp.NewShares[j] + r3msg1 := NewDGRound3Message1(Pj, Pi, share) + temp.dgRound3Message1s[i] = r3msg1 + out.Messages = append(out.Messages, r3msg1) + } + + r3msg2 := NewDGRound3Message2( + params.NewParties().IDs().Exclude(Pi), Pi, temp.VD) + temp.dgRound3Message2s[i] = r3msg2 + out.Messages = append(out.Messages, r3msg2) + + return out, nil +} + +// ReshareRound4 verifies new committee parameters and old committee +// shares, computes the new Xi and BigXj, and produces FacProof + +// ACK messages. Only new committee members produce output. +// +// r2NewMsgs are DGRound2Message1 broadcasts from new committee. +// r3P2P[j] is old party j's DGRound3Message1 (P2P share). +// r3Bcast[j] is old party j's DGRound3Message2 (decommitment). +func ReshareRound4(ctx context.Context, state *ReshareState, r2NewMsgs []*tss.Message, r3P2P, r3Bcast []*tss.Message) (*ReshareRoundOutput, error) { + params, save, temp := state.params, state.save, state.temp + tss.MergeMsgs(temp.dgRound2Message1s, r2NewMsgs) + tss.MergeMsgs(temp.dgRound3Message1s, r3P2P) + tss.MergeMsgs(temp.dgRound3Message2s, r3Bcast) + out := &ReshareRoundOutput{} + + if !params.IsNewCommittee() { + return out, nil + } + + dlnVerifier := keygen.NewDlnProofVerifier(params.Concurrency()) + Pi := params.PartyID() + i := newIndex(params) + + // Parameter validation + h1H2Map := make(map[string]struct{}, len(r2NewMsgs)*2) + // Single modulus map for both PaillierN and NTilde: catches cross-party + // collisions (e.g., Party A's PaillierN == Party B's NTilde) that separate + // maps would miss. Such a collision lets A forge range proofs against B. + modulusMap := make(map[string]struct{}, len(r2NewMsgs)*2) + paiProofCulprits := make([]*tss.PartyID, len(r2NewMsgs)) + dlnProof1FailCulprits := make([]*tss.PartyID, len(r2NewMsgs)) + dlnProof2FailCulprits := make([]*tss.PartyID, len(r2NewMsgs)) + wg := new(sync.WaitGroup) + gctx, gcancel := context.WithCancel(ctx) + defer gcancel() + for j, msg := range r2NewMsgs { + r2msg1 := msg.Content.(*DGRound2Message1) + paiPK, NTildej, H1j, H2j := r2msg1.PaillierPK, + r2msg1.NTilde, r2msg1.H1, r2msg1.H2 + if H1j.Cmp(H2j) == 0 { + return nil, tss.NewError(errors.New("h1j == h2j"), TaskName, 4, Pi, msg.From) + } + if H1j.Cmp(reshareOne) == 0 || H2j.Cmp(reshareOne) == 0 { + return nil, tss.NewError(errors.New("h1j or h2j is 1"), TaskName, 4, Pi, msg.From) + } + if paiPK.N.BitLen() < resharePaiBitsLen { + return nil, tss.NewError(errors.New("paillier N insufficient bits"), TaskName, 4, Pi, msg.From) + } + if paiPK.N.Bit(0) == 0 { + return nil, tss.NewError(errors.New("even paillier N"), TaskName, 4, Pi, msg.From) + } + if paiPK.N.ProbablyPrime(20) { + return nil, tss.NewError(errors.New("prime paillier N"), TaskName, 4, Pi, msg.From) + } + sqrtN := new(big.Int).Sqrt(paiPK.N) + if new(big.Int).Mul(sqrtN, sqrtN).Cmp(paiPK.N) == 0 { + return nil, tss.NewError(errors.New("perfect-square paillier N"), TaskName, 4, Pi, msg.From) + } + if NTildej.BitLen() < resharePaiBitsLen { + return nil, tss.NewError(errors.New("NTildej insufficient bits"), TaskName, 4, Pi, msg.From) + } + if NTildej.Bit(0) == 0 { + return nil, tss.NewError(errors.New("even NTildej"), TaskName, 4, Pi, msg.From) + } + if NTildej.ProbablyPrime(20) { + return nil, tss.NewError(errors.New("prime NTildej"), TaskName, 4, Pi, msg.From) + } + sqrtNT := new(big.Int).Sqrt(NTildej) + if new(big.Int).Mul(sqrtNT, sqrtNT).Cmp(NTildej) == 0 { + return nil, tss.NewError(errors.New("perfect-square NTildej"), TaskName, 4, Pi, msg.From) + } + if paiPK.N.Cmp(NTildej) == 0 { + return nil, tss.NewError(errors.New("paillier N == NTilde"), TaskName, 4, Pi, msg.From) + } + if new(big.Int).GCD(nil, nil, H1j, NTildej).Cmp(reshareOne) != 0 { + return nil, tss.NewError(errors.New("h1j not coprime with NTildej"), TaskName, 4, Pi, msg.From) + } + if new(big.Int).GCD(nil, nil, H2j, NTildej).Cmp(reshareOne) != 0 { + return nil, tss.NewError(errors.New("h2j not coprime with NTildej"), TaskName, 4, Pi, msg.From) + } + h1Hex, h2Hex := hex.EncodeToString(H1j.Bytes()), hex.EncodeToString(H2j.Bytes()) + if _, found := h1H2Map[h1Hex]; found { + return nil, tss.NewError(errors.New("duplicate h1j"), TaskName, 4, Pi, msg.From) + } + if _, found := h1H2Map[h2Hex]; found { + return nil, tss.NewError(errors.New("duplicate h2j"), TaskName, 4, Pi, msg.From) + } + h1H2Map[h1Hex], h1H2Map[h2Hex] = struct{}{}, struct{}{} + paiNHex := hex.EncodeToString(paiPK.N.Bytes()) + if _, found := modulusMap[paiNHex]; found { + return nil, tss.NewError(errors.New("duplicate modulus (paillier N)"), TaskName, 4, Pi, msg.From) + } + modulusMap[paiNHex] = struct{}{} + ntHex := hex.EncodeToString(NTildej.Bytes()) + if _, found := modulusMap[ntHex]; found { + return nil, tss.NewError(errors.New("duplicate modulus (NTilde)"), TaskName, 4, Pi, msg.From) + } + modulusMap[ntHex] = struct{}{} + + nTasks := 1 + if !params.NoProofDLN() { + nTasks = 3 + } + wg.Add(nTasks) + go func(j int, msg *tss.Message, r2msg1 *DGRound2Message1) { + defer wg.Done() + if gctx.Err() != nil { + return + } + if params.NoProofMod() { + return + } + modProof := r2msg1.ModProof + if modProof == nil { + paiProofCulprits[j] = msg.From + gcancel() + return + } + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + if ok := modProof.Verify(ContextJ, paiPK.N); !ok { + paiProofCulprits[j] = msg.From + gcancel() + } + }(j, msg, r2msg1) + if !params.NoProofDLN() { + _j, _msg := j, msg + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + dlnVerifier.VerifyDLNProof(r2msg1.DLNProof1, ContextJ, H1j, H2j, NTildej, func(isValid bool) { + if !isValid { + dlnProof1FailCulprits[_j] = _msg.From + gcancel() + } + wg.Done() + }) + dlnVerifier.VerifyDLNProof(r2msg1.DLNProof2, ContextJ, H2j, H1j, NTildej, func(isValid bool) { + if !isValid { + dlnProof2FailCulprits[_j] = _msg.From + gcancel() + } + wg.Done() + }) + } + } + wg.Wait() + if err := ctx.Err(); err != nil { + return nil, err + } + for _, culprits := range [][]*tss.PartyID{paiProofCulprits, dlnProof1FailCulprits, dlnProof2FailCulprits} { + for _, c := range culprits { + if c != nil { + return nil, tss.NewError(errors.New("proof verification failed"), TaskName, 4, Pi, c) + } + } + } + + // Save NTilde, H1, H2 from new committee + for j, msg := range r2NewMsgs { + if j == i { + continue + } + r2msg1 := msg.Content.(*DGRound2Message1) + save.NTildej[j] = r2msg1.NTilde + save.H1j[j] = r2msg1.H1 + save.H2j[j] = r2msg1.H2 + } + + // Verify old committee shares and commitments + modQ := common.ModInt(params.EC().Params().N) + newXi := big.NewInt(0) + vjc := make([][]*crypto.ECPoint, len(params.OldParties().IDs())) + for j := 0; j < len(vjc); j++ { + r1msg := temp.dgRound1Messages[j].Content.(*DGRound1Message) + r3msg2 := r3Bcast[j].Content.(*DGRound3Message2) + vCj, vDj := r1msg.VCommitment, r3msg2.VDeCommitment + cmtDeCmt := commitments.HashCommitDecommit{C: vCj, D: vDj} + ok, flatVs := cmtDeCmt.DeCommit() + if !ok || len(flatVs) != (params.NewThreshold()+1)*2 { + return nil, tss.NewError(errors.New("v decommit failed"), TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + vj, err := crypto.UnFlattenECPoints(params.EC(), flatVs) + if err != nil { + return nil, tss.NewError(err, TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + vjc[j] = vj + + r3msg1 := r3P2P[j].Content.(*DGRound3Message1) + myKey := Pi.KeyInt().Bytes() + if !bytes.Equal(r3msg1.ReceiverID, myKey) { + return nil, tss.NewError(errors.New("receiverId mismatch"), TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + sharej := &vss.Share{ + Threshold: params.NewThreshold(), + ID: Pi.KeyInt(), + Share: r3msg1.Share, + } + if ok := sharej.Verify(params.EC(), params.NewThreshold(), vj); !ok { + return nil, tss.NewError(errors.New("vss share verify failed"), TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + newXi = new(big.Int).Add(newXi, sharej.Share) + } + newXi = new(big.Int).Mod(newXi, params.EC().Params().N) + if newXi.Sign() == 0 { + return nil, errors.New("newXi is zero") + } + + // Compute Vc + var err error + Vc := make([]*crypto.ECPoint, params.NewThreshold()+1) + for c := 0; c <= params.NewThreshold(); c++ { + Vc[c] = vjc[0][c] + for j := 1; j < len(vjc); j++ { + Vc[c], err = Vc[c].Add(vjc[j][c]) + if err != nil { + return nil, errors2.Wrapf(err, "Vc[%d].Add(vjc[%d][%d])", c, j, c) + } + } + } + if !Vc[0].Equals(save.ECDSAPub) { + return nil, errors.New("V_0 != ECDSAPub") + } + + // Compute newBigXjs + newKs := make([]*big.Int, 0, params.NewPartyCount()) + newBigXjs := make([]*crypto.ECPoint, params.NewPartyCount()) + culprits := make([]*tss.PartyID, 0) + for j := 0; j < params.NewPartyCount(); j++ { + Pj := params.NewParties().IDs()[j] + kj := Pj.KeyInt() + newBigXj := Vc[0] + newKs = append(newKs, kj) + z := new(big.Int).SetInt64(1) + for c := 1; c <= params.NewThreshold(); c++ { + z = modQ.Mul(z, kj) + newBigXj, err = newBigXj.Add(Vc[c].ScalarMult(z)) + if err != nil { + culprits = append(culprits, Pj) + break + } + } + if newBigXj.IsIdentity() { + culprits = append(culprits, Pj) + } else { + newBigXjs[j] = newBigXj + } + } + if len(culprits) > 0 { + return nil, tss.NewError(errors.New("newBigXj identity or computation error"), TaskName, 4, Pi, culprits...) + } + + temp.newXi = newXi + temp.newKs = newKs + temp.newBigXjs = newBigXjs + + // Send FacProof to new parties + for j, Pj := range params.NewParties().IDs() { + if j == i { + continue + } + var fp *facproof.ProofFac + if !params.NoProofFac() { + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + fp, err = facproof.NewProof(ContextJ, params.EC(), save.PaillierSK.N, + save.NTildej[j], save.H1j[j], save.H2j[j], + save.PaillierSK.P, save.PaillierSK.Q, params.Rand()) + if err != nil { + return nil, fmt.Errorf("round 5 fac proof for party %d: %w", j, err) + } + } + r4msg1 := NewDGRound4Message1(Pj, Pi, fp) + out.Messages = append(out.Messages, r4msg1) + } + + // ACK to both committees + r4msg2 := NewDGRound4Message2(params.OldAndNewParties(), Pi) + temp.dgRound4Message2s[i] = r4msg2 + out.Messages = append(out.Messages, r4msg2) + + return out, nil +} + +// ReshareRound5 verifies FacProofs and saves the new key share. +// Only new committee members produce output (the final Save). +// +// r4P2P[j] is new party j's DGRound4Message1 (P2P FacProof). +// r4Bcast[j] is new party j's DGRound4Message2 (ACK broadcast). +func ReshareRound5(state *ReshareState, r4P2P, r4Bcast []*tss.Message) (*ReshareRoundOutput, error) { + params, save, temp, input := state.params, state.save, state.temp, state.input + tss.MergeMsgs(temp.dgRound4Message1s, r4P2P) + tss.MergeMsgs(temp.dgRound4Message2s, r4Bcast) + out := &ReshareRoundOutput{} + + Pi := params.PartyID() + i := newIndex(params) + + if params.IsNewCommittee() { + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(i))) + save.BigXj = temp.newBigXjs + save.ShareID = Pi.KeyInt() + save.Xi = temp.newXi + save.Ks = temp.newKs + + for j, msg := range temp.dgRound2Message1s { + if j == i { + continue + } + r2msg1 := msg.Content.(*DGRound2Message1) + save.PaillierPKs[j] = r2msg1.PaillierPK + } + for j, msg := range r4P2P { + if j == i { + continue + } + r4msg1 := msg.Content.(*DGRound4Message1) + receiverId := r4msg1.ReceiverID + if !bytes.Equal(receiverId, Pi.Key) { + return nil, tss.NewError(errors.New("DGRound4Message1 receiverId mismatch"), + TaskName, 5, Pi, params.NewParties().IDs()[j]) + } + if params.NoProofFac() { + continue + } + proof := r4msg1.FacProof + if proof == nil { + return nil, tss.NewError(errors.New("facProof missing"), TaskName, 5, Pi, params.NewParties().IDs()[j]) + } + if ok := proof.Verify(ContextI, params.EC(), save.PaillierPKs[j].N, + save.NTildei, save.H1i, save.H2i); !ok { + return nil, tss.NewError(errors.New("facProof verify failed"), + TaskName, 5, Pi, params.NewParties().IDs()[j]) + } + } + out.Save = save + } + + // Zero old Xi + if params.IsOldCommittee() { + input.Xi.SetInt64(0) + } + + return out, nil +} diff --git a/tss-lib/ecdsa/resharing/round_fn_test.go b/tss-lib/ecdsa/resharing/round_fn_test.go new file mode 100644 index 0000000..39c87c2 --- /dev/null +++ b/tss-lib/ecdsa/resharing/round_fn_test.go @@ -0,0 +1,572 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/signing" + "github.com/hemilabs/x/tss-lib/v3/testutil" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestRoundFnReshareAndSign does keygen(3) → reshare(3→3) → sign(3) +// using pure round functions throughout. +func TestRoundFnReshareAndSign(t *testing.T) { + const n = 3 + const threshold = 1 // 2-of-3 + + // ---- Keygen ---- + preParamsOld := testutil.LoadPreParams(t, n) + oldPIDs := tss.GenerateTestPartyIDs(n) + oldCtx := tss.NewPeerContext(oldPIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), oldCtx, oldPIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParamsOld[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + + oldKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + oldKeys[i] = *out.Save + } + t.Logf("keygen done: ECDSAPub = (%x...)", oldKeys[0].ECDSAPub.X().Bytes()[:4]) + + // ---- Reshare: 3 old → 3 new (disjoint) ---- + newPIDs := tss.GenerateTestPartyIDs(n) // fresh random keys, indices 0..n-1 + newCtx := tss.NewPeerContext(newPIDs) + + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + // Create states for old + new parties. + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + + // Round 1: old committee produces broadcasts + oldR1Msgs := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + // New committee: Round1 is a no-op, just creates state + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofMod() + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + // Round 2: new committee produces DGRound2Message1 (to new) + DGRound2Message2 (ACK to old) + newR2Msg1s := make([]*tss.Message, n) // broadcast to new + newR2Msg2s := make([]*tss.Message, n) // ACK to old + for i := 0; i < n; i++ { + out, err := ReshareRound2(newStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound2Message1: + newR2Msg1s[i] = pm + case *DGRound2Message2: + newR2Msg2s[i] = pm + } + } + } + // Old committee: Round2 is a no-op (they're not new committee) + for i := 0; i < n; i++ { + _, err := ReshareRound2(oldStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(old)[%d]: %v", i, err) + } + } + // Fill self-messages for new committee + for i := 0; i < n; i++ { + if newR2Msg1s[i] == nil { + newR2Msg1s[i] = newStates[i].temp.dgRound2Message1s[i] + } + if newR2Msg2s[i] == nil { + newR2Msg2s[i] = newStates[i].temp.dgRound2Message2s[i] + } + } + + // Round 3: old committee sends shares P2P + decommit broadcast + oldR3P2P := make([][]*tss.Message, n) // oldR3P2P[newIdx][oldIdx] + oldR3Bcast := make([]*tss.Message, n) // oldR3Bcast[oldIdx] + for i := 0; i < n; i++ { + oldR3P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound3(oldStates[i], newR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(old)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound3Message1: + // P2P to new party + for _, to := range pm.To { + oldR3P2P[to.Index][i] = pm + } + case *DGRound3Message2: + oldR3Bcast[i] = pm + } + } + } + // New committee: Round3 is a no-op + for i := 0; i < n; i++ { + _, err := ReshareRound3(newStates[i], newR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(new)[%d]: %v", i, err) + } + } + + // Round 4: new committee verifies and produces FacProof + ACK + newR4P2P := make([][]*tss.Message, n) // newR4P2P[newIdx][senderNewIdx] + newR4Bcast := make([]*tss.Message, n) // newR4Bcast[newIdx] + for i := 0; i < n; i++ { + newR4P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound4(context.Background(), newStates[i], newR2Msg1s, oldR3P2P[i], oldR3Bcast) + if err != nil { + t.Fatalf("ReshareRound4(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound4Message1: + for _, to := range pm.To { + newR4P2P[to.Index][i] = pm + } + case *DGRound4Message2: + newR4Bcast[i] = pm + } + } + } + // Old committee: Round4 is a no-op + for i := 0; i < n; i++ { + _, err := ReshareRound4(context.Background(), oldStates[i], newR2Msg1s, nil, nil) + if err != nil { + t.Fatalf("ReshareRound4(old)[%d]: %v", i, err) + } + } + // Fill self-messages + for i := 0; i < n; i++ { + if newR4Bcast[i] == nil { + newR4Bcast[i] = newStates[i].temp.dgRound4Message2s[i] + } + } + + // Round 5: new committee finalizes + newKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := ReshareRound5(newStates[i], newR4P2P[i], newR4Bcast) + if err != nil { + t.Fatalf("ReshareRound5(new)[%d]: %v", i, err) + } + if out.Save == nil { + t.Fatalf("ReshareRound5(new)[%d]: no Save", i) + } + newKeys[i] = *out.Save + } + // Old committee: Round5 zeros Xi + for i := 0; i < n; i++ { + _, err := ReshareRound5(oldStates[i], nil, newR4Bcast) + if err != nil { + t.Fatalf("ReshareRound5(old)[%d]: %v", i, err) + } + } + + // Verify new keys have same ECDSAPub + for i := 1; i < n; i++ { + if !newKeys[i].ECDSAPub.Equals(newKeys[0].ECDSAPub) { + t.Fatalf("new party %d has different ECDSAPub", i) + } + } + if !newKeys[0].ECDSAPub.Equals(oldKeys[0].ECDSAPub) { + t.Fatal("new ECDSAPub != old ECDSAPub") + } + t.Log("reshare done: ECDSAPub preserved") + + // ---- Sign with new keys ---- + msgHash := sha256.Sum256([]byte("reshare test")) + m := new(big.Int).SetBytes(msgHash[:]) + + sigStates := make([]*signing.SigningState, n) + sigR1P2P := make([][]*tss.Message, n) + sigR1Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + sigR1P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), newCtx, newPIDs[i], n, threshold) + st, out, err := signing.SignRound1(params, newKeys[i], m, nil, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + sigStates[i] = st + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + sigR1Bcast[i] = pm + } else { + for _, to := range pm.To { + sigR1P2P[to.Index][i] = pm + } + } + } + } + + // Signing rounds 2-9 + finalize + sigR2P2P := make([][]*tss.Message, n) + for i := 0; i < n; i++ { + sigR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := signing.SignRound2(context.Background(), sigStates[i], sigR1P2P[i], sigR1Bcast) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + for _, to := range pm.To { + sigR2P2P[to.Index][i] = pm + } + } + } + sigR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound3(context.Background(), sigStates[i], sigR2P2P[i]) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + sigR3[i] = out.Messages[0] + } + sigR4 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound4(sigStates[i], sigR3) + if err != nil { + t.Fatalf("SignRound4[%d]: %v", i, err) + } + sigR4[i] = out.Messages[0] + } + sigR5 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound5(sigStates[i], sigR4) + if err != nil { + t.Fatalf("SignRound5[%d]: %v", i, err) + } + sigR5[i] = out.Messages[0] + } + sigR6 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound6(sigStates[i]) + if err != nil { + t.Fatalf("SignRound6[%d]: %v", i, err) + } + sigR6[i] = out.Messages[0] + } + sigR7 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound7(sigStates[i], sigR5, sigR6) + if err != nil { + t.Fatalf("SignRound7[%d]: %v", i, err) + } + sigR7[i] = out.Messages[0] + } + sigR8 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound8(sigStates[i]) + if err != nil { + t.Fatalf("SignRound8[%d]: %v", i, err) + } + sigR8[i] = out.Messages[0] + } + sigR9 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound9(sigStates[i], sigR7, sigR8) + if err != nil { + t.Fatalf("SignRound9[%d]: %v", i, err) + } + sigR9[i] = out.Messages[0] + } + for i := 0; i < n; i++ { + out, err := signing.SignFinalize(sigStates[i], sigR9) + if err != nil { + t.Fatalf("SignFinalize[%d]: %v", i, err) + } + pk := ecdsa.PublicKey{ + Curve: tss.S256(), + X: newKeys[0].ECDSAPub.X(), + Y: newKeys[0].ECDSAPub.Y(), + } + r := new(big.Int).SetBytes(out.Signature.R) + s := new(big.Int).SetBytes(out.Signature.S) + if !ecdsa.Verify(&pk, msgHash[:], r, s) { + t.Fatalf("party %d: signature verification failed after reshare", i) + } + } + t.Log("sign after reshare: verified") +} + +// TestRoundFnReshareNoProofDLN does reshare with DLN proofs disabled +// (on-chain SNARK mode). +func TestRoundFnReshareNoProofDLN(t *testing.T) { + const n = 3 + const threshold = 1 + + // Keygen (same as main test) + preParamsOld := testutil.LoadPreParams(t, n) + oldPIDs := tss.GenerateTestPartyIDs(n) + oldCtx := tss.NewPeerContext(oldPIDs) + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), oldCtx, oldPIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParamsOld[i]) + if err != nil { + t.Fatalf("kg R1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, _ := keygen.Round2(context.Background(), kgStates[i], kgR1) + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, _ := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + kgR3[i] = out.Messages[0] + } + oldKeys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, _ := keygen.Round4(context.Background(), kgStates[i], kgR3) + oldKeys[i] = *out.Save + } + + // Reshare with no-proof flags + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + newR2Msg1s := make([]*tss.Message, n) + newR2Msg2s := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := ReshareRound2(newStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound2Message1: + newR2Msg1s[i] = pm + case *DGRound2Message2: + newR2Msg2s[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, err := ReshareRound2(oldStates[i], oldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(old)[%d]: %v", i, err) + } + } + for i := 0; i < n; i++ { + if newR2Msg1s[i] == nil { + newR2Msg1s[i] = newStates[i].temp.dgRound2Message1s[i] + } + if newR2Msg2s[i] == nil { + newR2Msg2s[i] = newStates[i].temp.dgRound2Message2s[i] + } + } + + oldR3P2P := make([][]*tss.Message, n) + oldR3Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + oldR3P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound3(oldStates[i], newR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(old)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound3Message1: + for _, to := range pm.To { + oldR3P2P[to.Index][i] = pm + } + case *DGRound3Message2: + oldR3Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound3(newStates[i], newR2Msg2s) + } + + newR4P2P := make([][]*tss.Message, n) + newR4Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + newR4P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound4(context.Background(), newStates[i], newR2Msg1s, oldR3P2P[i], oldR3Bcast) + if err != nil { + t.Fatalf("ReshareRound4(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound4Message1: + for _, to := range pm.To { + newR4P2P[to.Index][i] = pm + } + case *DGRound4Message2: + newR4Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound4(context.Background(), oldStates[i], newR2Msg1s, nil, nil) + } + for i := 0; i < n; i++ { + if newR4Bcast[i] == nil { + newR4Bcast[i] = newStates[i].temp.dgRound4Message2s[i] + } + } + + for i := 0; i < n; i++ { + out, err := ReshareRound5(newStates[i], newR4P2P[i], newR4Bcast) + if err != nil { + t.Fatalf("ReshareRound5(new)[%d]: %v", i, err) + } + if out.Save == nil { + t.Fatalf("ReshareRound5(new)[%d]: no Save", i) + } + if !out.Save.ECDSAPub.Equals(oldKeys[0].ECDSAPub) { + t.Fatal("ECDSAPub changed after reshare") + } + } + for i := 0; i < n; i++ { + _, _ = ReshareRound5(oldStates[i], nil, newR4Bcast) + } + t.Log("reshare with all proofs disabled: passed") +} diff --git a/tss-lib/ecdsa/resharing/round_state.go b/tss-lib/ecdsa/resharing/round_state.go new file mode 100644 index 0000000..b3ce2ea --- /dev/null +++ b/tss-lib/ecdsa/resharing/round_state.go @@ -0,0 +1,41 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// ReshareState holds all mutable state between resharing rounds. +// A single node may be in both the old and new committee; the +// ReSharingParameters encode which roles this party plays. +type ReshareState struct { + params *tss.ReSharingParameters + input *keygen.LocalPartySaveData // existing key (old committee) + save *keygen.LocalPartySaveData // new key being built + temp *localTempData +} + +// ReshareRoundOutput holds the outbound messages and artifacts +// produced by a single resharing round function. +type ReshareRoundOutput struct { + // Messages to send. + Messages []*tss.Message + + // Save is non-nil only after ReshareRound5 (final new-committee round). + Save *keygen.LocalPartySaveData + + // Poly contains the VSS polynomial coefficients for SNARK + // witness extraction. Non-nil only on ReshareRound1 (old committee). + Poly []*big.Int + + // NewVs contains Feldman VSS commitments for SNARK witness. + // Non-nil only on ReshareRound1 (old committee). + NewVs []*crypto.ECPoint +} diff --git a/tss-lib/ecdsa/resharing/rounds.go b/tss-lib/ecdsa/resharing/rounds.go deleted file mode 100644 index 568a13d..0000000 --- a/tss-lib/ecdsa/resharing/rounds.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - TaskName = "ecdsa-resharing" -) - -type ( - base struct { - *tss.ReSharingParameters - temp *localTempData - input, save *keygen.LocalPartySaveData - out chan<- tss.Message - end chan<- *keygen.LocalPartySaveData - oldOK, // old committee "ok" tracker - newOK []bool // `ok` tracks parties which have been verified by Update(); this one is for the new committee - started bool - number int - } - round1 struct { - *base - } - round2 struct { - *round1 - } - round3 struct { - *round2 - } - round4 struct { - *round3 - } - round5 struct { - *round4 - } -) - -var ( - _ tss.Round = (*round1)(nil) - _ tss.Round = (*round2)(nil) - _ tss.Round = (*round3)(nil) - _ tss.Round = (*round4)(nil) - _ tss.Round = (*round5)(nil) -) - -// ----- // - -func (round *base) Params() *tss.Parameters { - return round.ReSharingParameters.Parameters -} - -func (round *base) ReSharingParams() *tss.ReSharingParameters { - return round.ReSharingParameters -} - -func (round *base) RoundNumber() int { - return round.number -} - -// CanProceed is inherited by other rounds -func (round *base) CanProceed() bool { - if !round.started { - return false - } - for _, ok := range append(round.oldOK, round.newOK...) { - if !ok { - return false - } - } - return true -} - -// WaitingFor is called by a Party for reporting back to the caller -func (round *base) WaitingFor() []*tss.PartyID { - oldPs := round.OldParties().IDs() - newPs := round.NewParties().IDs() - idsMap := make(map[*tss.PartyID]bool) - ids := make([]*tss.PartyID, 0, len(round.oldOK)) - for j, ok := range round.oldOK { - if ok { - continue - } - idsMap[oldPs[j]] = true - } - for j, ok := range round.newOK { - if ok { - continue - } - idsMap[newPs[j]] = true - } - // consolidate into the list - for id := range idsMap { - ids = append(ids, id) - } - return ids -} - -func (round *base) WrapError(err error, culprits ...*tss.PartyID) *tss.Error { - return tss.NewError(err, TaskName, round.number, round.PartyID(), culprits...) -} - -// ----- // - -// `oldOK` tracks parties which have been verified by Update() -func (round *base) resetOK() { - for j := range round.oldOK { - round.oldOK[j] = false - } - for j := range round.newOK { - round.newOK[j] = false - } -} - -// sets all pairings in `oldOK` to true -func (round *base) allOldOK() { - for j := range round.oldOK { - round.oldOK[j] = true - } -} - -// sets all pairings in `newOK` to true -func (round *base) allNewOK() { - for j := range round.newOK { - round.newOK[j] = true - } -} - -// get ssid from local params -func (round *base) getSSID() ([]byte, error) { - ssidList := []*big.Int{round.EC().Params().P, round.EC().Params().N, round.EC().Params().B, round.EC().Params().Gx, round.EC().Params().Gy} // ec curve - ssidList = append(ssidList, round.Parties().IDs().Keys()...) // parties - BigXjList, err := crypto.FlattenECPoints(round.input.BigXj) - if err != nil { - return nil, round.WrapError(errors.New("read BigXj failed"), round.PartyID()) - } - ssidList = append(ssidList, BigXjList...) // BigXj - ssidList = append(ssidList, round.input.NTildej...) // NTilde - ssidList = append(ssidList, round.input.H1j...) // h1 - ssidList = append(ssidList, round.input.H2j...) // h2 - ssidList = append(ssidList, big.NewInt(int64(round.number))) // round number - ssidList = append(ssidList, round.temp.ssidNonce) - ssid := common.SHA512_256i(ssidList...).Bytes() - - return ssid, nil -} diff --git a/tss-lib/ecdsa/resharing/ssid_test.go b/tss-lib/ecdsa/resharing/ssid_test.go new file mode 100644 index 0000000..f08ca72 --- /dev/null +++ b/tss-lib/ecdsa/resharing/ssid_test.go @@ -0,0 +1,540 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "bytes" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// buildTestResharingFixture creates deterministic ReSharingParameters and +// matching keygen save data for SSID and index tests. The returned +// objects are minimal but structurally valid for getReshareSSID. +func buildTestResharingFixture(t *testing.T) (params *tss.ReSharingParameters, input *keygen.LocalPartySaveData, temp *localTempData, oldPIDs tss.SortedPartyIDs, newPIDs tss.SortedPartyIDs) { + t.Helper() + ec := tss.S256() + + // Build deterministic party IDs (3 old, 3 new). + oldPIDs = makeDeterministicPartyIDs(3, 100) + newPIDs = makeDeterministicPartyIDs(3, 200) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + // Parameters from the perspective of old party 0. + params = tss.NewReSharingParameters(ec, oldCtx, newCtx, oldPIDs[0], 3, 1, 3, 1) + + // Build minimal LocalPartySaveData with BigXj, NTildej, H1j, H2j. + n := 3 + save := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + // Use scalar base mult to produce valid on-curve points. + scalar := big.NewInt(int64(i + 7)) + pt := crypto.ScalarBaseMult(ec, scalar) + save.BigXj[i] = pt + save.NTildej[i] = big.NewInt(int64(1000 + i)) + save.H1j[i] = big.NewInt(int64(2000 + i)) + save.H2j[i] = big.NewInt(int64(3000 + i)) + } + + input = &save + temp = &localTempData{ + ssidNonce: big.NewInt(42), + } + return +} + +// makeDeterministicPartyIDs creates sorted party IDs with keys derived from +// a base offset so that tests are reproducible. +func makeDeterministicPartyIDs(count int, base int64) tss.SortedPartyIDs { + ids := make(tss.UnSortedPartyIDs, count) + for i := 0; i < count; i++ { + key := big.NewInt(base + int64(i) + 1) // +1 to avoid zero key + ids[i] = tss.NewPartyID( + big.NewInt(base+int64(i)).String(), + "P", + key, + ) + } + return tss.SortPartyIDs(ids) +} + +// ---------- getReshareSSID tests ---------- + +func TestGetReshareSSIDDeterministic(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + + ssid1, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID call 1: %v", err) + } + ssid2, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID call 2: %v", err) + } + + if !bytes.Equal(ssid1, ssid2) { + t.Fatalf("same inputs must produce identical SSIDs:\n ssid1=%x\n ssid2=%x", ssid1, ssid2) + } + if len(ssid1) == 0 { + t.Fatal("SSID must be non-empty") + } +} + +func TestGetReshareSSIDWithCeremonyID(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + + // Baseline: no ceremony ID. + ssidNoCID, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID (no CID): %v", err) + } + + // Set a ceremony ID and recompute. + params.SetCeremonyID([]byte("ceremony-alpha")) + ssidWithCID, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID (with CID): %v", err) + } + + if bytes.Equal(ssidNoCID, ssidWithCID) { + t.Fatal("CeremonyID must change the SSID, but got identical values") + } + + // Different ceremony ID produces a different SSID again. + params.SetCeremonyID([]byte("ceremony-beta")) + ssidWithCID2, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID (with CID2): %v", err) + } + if bytes.Equal(ssidWithCID, ssidWithCID2) { + t.Fatal("different CeremonyIDs must produce different SSIDs") + } + + // Determinism: same ceremony ID twice. + ssidWithCID2Again, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID (with CID2 again): %v", err) + } + if !bytes.Equal(ssidWithCID2, ssidWithCID2Again) { + t.Fatal("same CeremonyID must produce identical SSIDs on repeated calls") + } +} + +func TestGetReshareSSIDDifferentRoundNumbers(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + + ssids := make(map[string]int) + for round := 1; round <= 5; round++ { + ssid, err := getReshareSSID(params, input, temp, round) + if err != nil { + t.Fatalf("getReshareSSID(round=%d): %v", round, err) + } + key := string(ssid) + if prev, exists := ssids[key]; exists { + t.Fatalf("round %d produced the same SSID as round %d", round, prev) + } + ssids[key] = round + } +} + +func TestGetReshareSSIDDifferentNonce(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + + ssid1, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID(nonce=42): %v", err) + } + + temp2 := &localTempData{ssidNonce: big.NewInt(99)} + ssid2, err := getReshareSSID(params, input, temp2, 1) + if err != nil { + t.Fatalf("getReshareSSID(nonce=99): %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different ssidNonce values must produce different SSIDs") + } +} + +func TestGetReshareSSIDDifferentThresholds(t *testing.T) { + ec := tss.S256() + oldPIDs := makeDeterministicPartyIDs(4, 100) + newPIDs := makeDeterministicPartyIDs(4, 200) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + n := 4 + save := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + pt := crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + save.BigXj[i] = pt + save.NTildej[i] = big.NewInt(int64(1000 + i)) + save.H1j[i] = big.NewInt(int64(2000 + i)) + save.H2j[i] = big.NewInt(int64(3000 + i)) + } + temp := &localTempData{ssidNonce: big.NewInt(1)} + + params1 := tss.NewReSharingParameters(ec, oldCtx, newCtx, oldPIDs[0], 4, 1, 4, 1) + ssid1, err := getReshareSSID(params1, &save, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID(threshold=1): %v", err) + } + + params2 := tss.NewReSharingParameters(ec, oldCtx, newCtx, oldPIDs[0], 4, 2, 4, 2) + ssid2, err := getReshareSSID(params2, &save, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID(threshold=2): %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different thresholds must produce different SSIDs") + } +} + +// ---------- oldIndex / newIndex tests ---------- + +func TestOldIndexFindsCorrectIndex(t *testing.T) { + ec := tss.S256() + oldPIDs := makeDeterministicPartyIDs(3, 100) + newPIDs := makeDeterministicPartyIDs(3, 200) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + for i, pid := range oldPIDs { + params := tss.NewReSharingParameters(ec, oldCtx, newCtx, pid, 3, 1, 3, 1) + got := oldIndex(params) + if got != i { + t.Errorf("oldIndex for party %d: expected %d, got %d", i, i, got) + } + } +} + +func TestOldIndexReturnsNegOneForNonMember(t *testing.T) { + ec := tss.S256() + oldPIDs := makeDeterministicPartyIDs(3, 100) + newPIDs := makeDeterministicPartyIDs(3, 200) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + // A party in the new committee should not be found in the old committee. + for _, pid := range newPIDs { + params := tss.NewReSharingParameters(ec, oldCtx, newCtx, pid, 3, 1, 3, 1) + got := oldIndex(params) + if got != -1 { + t.Errorf("oldIndex for new-committee party %v: expected -1, got %d", pid, got) + } + } + + // A completely unrelated party. + stranger := tss.NewPartyID("stranger", "stranger", big.NewInt(999999)) + paramsStranger := tss.NewReSharingParameters(ec, oldCtx, newCtx, stranger, 3, 1, 3, 1) + if got := oldIndex(paramsStranger); got != -1 { + t.Errorf("oldIndex for stranger party: expected -1, got %d", got) + } +} + +func TestNewIndexFindsCorrectIndex(t *testing.T) { + ec := tss.S256() + oldPIDs := makeDeterministicPartyIDs(3, 100) + newPIDs := makeDeterministicPartyIDs(3, 200) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + for i, pid := range newPIDs { + params := tss.NewReSharingParameters(ec, oldCtx, newCtx, pid, 3, 1, 3, 1) + got := newIndex(params) + if got != i { + t.Errorf("newIndex for party %d: expected %d, got %d", i, i, got) + } + } +} + +func TestNewIndexReturnsNegOneForNonMember(t *testing.T) { + ec := tss.S256() + oldPIDs := makeDeterministicPartyIDs(3, 100) + newPIDs := makeDeterministicPartyIDs(3, 200) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + // Old-committee parties should not be found in new committee. + for _, pid := range oldPIDs { + params := tss.NewReSharingParameters(ec, oldCtx, newCtx, pid, 3, 1, 3, 1) + got := newIndex(params) + if got != -1 { + t.Errorf("newIndex for old-committee party %v: expected -1, got %d", pid, got) + } + } +} + +// TestOldAndNewIndexOverlappingParty verifies that when a party is a member +// of both the old and new committees, both oldIndex and newIndex return +// valid (non-negative) indices. +func TestOldAndNewIndexOverlappingParty(t *testing.T) { + ec := tss.S256() + + // Create party IDs where party 0 is in both committees. + sharedPID := tss.NewPartyID("shared", "shared", big.NewInt(50)) + oldOnly1 := tss.NewPartyID("old1", "old1", big.NewInt(51)) + oldOnly2 := tss.NewPartyID("old2", "old2", big.NewInt(52)) + newOnly1 := tss.NewPartyID("new1", "new1", big.NewInt(53)) + newOnly2 := tss.NewPartyID("new2", "new2", big.NewInt(54)) + + oldPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{sharedPID, oldOnly1, oldOnly2}) + newPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{sharedPID, newOnly1, newOnly2}) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + params := tss.NewReSharingParameters(ec, oldCtx, newCtx, sharedPID, 3, 1, 3, 1) + + oi := oldIndex(params) + ni := newIndex(params) + if oi < 0 { + t.Fatalf("overlapping party should be in old committee, got oldIndex=%d", oi) + } + if ni < 0 { + t.Fatalf("overlapping party should be in new committee, got newIndex=%d", ni) + } + // Verify the indices actually point to our shared party. + if oldPIDs[oi].KeyInt().Cmp(sharedPID.KeyInt()) != 0 { + t.Errorf("oldIndex %d does not point to shared party", oi) + } + if newPIDs[ni].KeyInt().Cmp(sharedPID.KeyInt()) != 0 { + t.Errorf("newIndex %d does not point to shared party", ni) + } +} + +// ---------- Cryptographic material sensitivity ---------- + +// TestGetReshareSSIDDifferentBigXj verifies that changing any single +// BigXj (old party public key share) changes the SSID. +func TestGetReshareSSIDDifferentBigXj(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + ssidOrig, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("original: %v", err) + } + + for i := 0; i < 3; i++ { + t.Run(big.NewInt(int64(i)).String(), func(t *testing.T) { + clone := cloneResharingSaveData(input, 3) + clone.BigXj[i] = crypto.ScalarBaseMult(tss.S256(), big.NewInt(999)) + ssid, err := getReshareSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated BigXj[%d]: %v", i, err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatalf("changing BigXj[%d] did not change SSID", i) + } + }) + } +} + +// TestGetReshareSSIDDifferentNTildej verifies that changing a single +// NTildej (Pedersen modulus) changes the SSID. +func TestGetReshareSSIDDifferentNTildej(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + ssidOrig, _ := getReshareSSID(params, input, temp, 1) + + clone := cloneResharingSaveData(input, 3) + clone.NTildej[1] = big.NewInt(99999) + ssid, err := getReshareSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated NTildej: %v", err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatal("changing NTildej did not change SSID") + } +} + +// TestGetReshareSSIDDifferentH1j verifies that changing a single H1j +// (Pedersen generator) changes the SSID. +func TestGetReshareSSIDDifferentH1j(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + ssidOrig, _ := getReshareSSID(params, input, temp, 1) + + clone := cloneResharingSaveData(input, 3) + clone.H1j[1] = big.NewInt(99999) + ssid, err := getReshareSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated H1j: %v", err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatal("changing H1j did not change SSID") + } +} + +// TestGetReshareSSIDDifferentH2j verifies that changing a single H2j +// (Pedersen generator) changes the SSID. +func TestGetReshareSSIDDifferentH2j(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + ssidOrig, _ := getReshareSSID(params, input, temp, 1) + + clone := cloneResharingSaveData(input, 3) + clone.H2j[1] = big.NewInt(99999) + ssid, err := getReshareSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated H2j: %v", err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatal("changing H2j did not change SSID") + } +} + +// ---------- Party key and party count sensitivity ---------- + +// TestGetReshareSSIDDifferentOldPartyKeys verifies that changing an old +// committee party's key changes the SSID. +func TestGetReshareSSIDDifferentOldPartyKeys(t *testing.T) { + ec := tss.S256() + newPIDs := makeDeterministicPartyIDs(3, 200) + newCtx := tss.NewPeerContext(newPIDs) + + makeSave := func(n int) *keygen.LocalPartySaveData { + s := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + s.BigXj[i] = crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + s.NTildej[i] = big.NewInt(int64(1000 + i)) + s.H1j[i] = big.NewInt(int64(2000 + i)) + s.H2j[i] = big.NewInt(int64(3000 + i)) + } + return &s + } + temp := &localTempData{ssidNonce: big.NewInt(1)} + + oldPIDs1 := makeDeterministicPartyIDs(3, 100) + oldCtx1 := tss.NewPeerContext(oldPIDs1) + params1 := tss.NewReSharingParameters(ec, oldCtx1, newCtx, oldPIDs1[0], 3, 1, 3, 1) + ssid1, err := getReshareSSID(params1, makeSave(3), temp, 1) + if err != nil { + t.Fatalf("old keys A: %v", err) + } + + oldPIDs2 := makeDeterministicPartyIDs(3, 500) // different base → different keys + oldCtx2 := tss.NewPeerContext(oldPIDs2) + params2 := tss.NewReSharingParameters(ec, oldCtx2, newCtx, oldPIDs2[0], 3, 1, 3, 1) + ssid2, err := getReshareSSID(params2, makeSave(3), temp, 1) + if err != nil { + t.Fatalf("old keys B: %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different old party keys must produce different SSIDs") + } +} + +// TestGetReshareSSIDDifferentNewPartyKeys verifies that changing a new +// committee party's key changes the SSID. +func TestGetReshareSSIDDifferentNewPartyKeys(t *testing.T) { + ec := tss.S256() + oldPIDs := makeDeterministicPartyIDs(3, 100) + oldCtx := tss.NewPeerContext(oldPIDs) + + makeSave := func(n int) *keygen.LocalPartySaveData { + s := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + s.BigXj[i] = crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + s.NTildej[i] = big.NewInt(int64(1000 + i)) + s.H1j[i] = big.NewInt(int64(2000 + i)) + s.H2j[i] = big.NewInt(int64(3000 + i)) + } + return &s + } + temp := &localTempData{ssidNonce: big.NewInt(1)} + + newPIDs1 := makeDeterministicPartyIDs(3, 200) + newCtx1 := tss.NewPeerContext(newPIDs1) + params1 := tss.NewReSharingParameters(ec, oldCtx, newCtx1, oldPIDs[0], 3, 1, 3, 1) + ssid1, err := getReshareSSID(params1, makeSave(3), temp, 1) + if err != nil { + t.Fatalf("new keys A: %v", err) + } + + newPIDs2 := makeDeterministicPartyIDs(3, 600) // different base → different keys + newCtx2 := tss.NewPeerContext(newPIDs2) + params2 := tss.NewReSharingParameters(ec, oldCtx, newCtx2, oldPIDs[0], 3, 1, 3, 1) + ssid2, err := getReshareSSID(params2, makeSave(3), temp, 1) + if err != nil { + t.Fatalf("new keys B: %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different new party keys must produce different SSIDs") + } +} + +// TestGetReshareSSIDDifferentPartyCount verifies that changing old or new +// party counts changes the SSID. +func TestGetReshareSSIDDifferentPartyCount(t *testing.T) { + ec := tss.S256() + temp := &localTempData{ssidNonce: big.NewInt(1)} + + makeSave := func(n int) *keygen.LocalPartySaveData { + s := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + s.BigXj[i] = crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + s.NTildej[i] = big.NewInt(int64(1000 + i)) + s.H1j[i] = big.NewInt(int64(2000 + i)) + s.H2j[i] = big.NewInt(int64(3000 + i)) + } + return &s + } + + // 3-old → 3-new + oldPIDs3 := makeDeterministicPartyIDs(3, 100) + newPIDs3 := makeDeterministicPartyIDs(3, 200) + params3 := tss.NewReSharingParameters(ec, + tss.NewPeerContext(oldPIDs3), tss.NewPeerContext(newPIDs3), + oldPIDs3[0], 3, 1, 3, 1) + ssid3, err := getReshareSSID(params3, makeSave(3), temp, 1) + if err != nil { + t.Fatalf("3→3: %v", err) + } + + // 4-old → 3-new (different old count, same new count) + oldPIDs4 := makeDeterministicPartyIDs(4, 100) + params4 := tss.NewReSharingParameters(ec, + tss.NewPeerContext(oldPIDs4), tss.NewPeerContext(newPIDs3), + oldPIDs4[0], 4, 1, 3, 1) + ssid4, err := getReshareSSID(params4, makeSave(4), temp, 1) + if err != nil { + t.Fatalf("4→3: %v", err) + } + + if bytes.Equal(ssid3, ssid4) { + t.Fatal("different old party counts must produce different SSIDs") + } +} + +// cloneResharingSaveData creates a shallow clone with deep-copied slices. +func cloneResharingSaveData(src *keygen.LocalPartySaveData, n int) *keygen.LocalPartySaveData { + dst := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + dst.BigXj[i] = src.BigXj[i] + dst.NTildej[i] = new(big.Int).Set(src.NTildej[i]) + dst.H1j[i] = new(big.Int).Set(src.H1j[i]) + dst.H2j[i] = new(big.Int).Set(src.H2j[i]) + } + return &dst +} + +// ---------- SSID length / format sanity ---------- + +func TestGetReshareSSIDLength(t *testing.T) { + params, input, temp, _, _ := buildTestResharingFixture(t) + ssid, err := getReshareSSID(params, input, temp, 1) + if err != nil { + t.Fatalf("getReshareSSID: %v", err) + } + // SHA-512/256 produces 32 bytes. The SSID is SHA512_256i(...).Bytes() + // which strips leading zeros, so it is at most 32 bytes. + if len(ssid) == 0 || len(ssid) > 32 { + t.Fatalf("SSID length should be in (0, 32], got %d", len(ssid)) + } +} diff --git a/tss-lib/ecdsa/resharing/test_helpers_test.go b/tss-lib/ecdsa/resharing/test_helpers_test.go new file mode 100644 index 0000000..af60209 --- /dev/null +++ b/tss-lib/ecdsa/resharing/test_helpers_test.go @@ -0,0 +1,791 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "context" + "errors" + "math/big" + "testing" + + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/dlnproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/facproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/modproof" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/testutil" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +const ( + reshareN = 3 + reshareThreshold = 1 // 2-of-3 +) + +// ReshareFixture holds accumulated state from running reshare rounds +// up to a certain point. Each "setupThrough*" function extends the +// fixture by one round, filling in the next set of message slices. +// +// Committee structure (3 old -> 3 new, disjoint): +// - Old committee: oldPIDs[0..2], oldStates[0..2], oldKeys[0..2] +// - New committee: newPIDs[0..2], newStates[0..2], preParamsNew[0..2] +// +// Message naming convention: +// - OldR1Msgs[oldIdx] = DGRound1Message broadcast by old party oldIdx +// - NewR2Msg1s[newIdx] = DGRound2Message1 broadcast by new party newIdx (Pedersen params) +// - NewR2Msg2s[newIdx] = DGRound2Message2 broadcast by new party newIdx (ACK to old) +// - OldR3P2P[newIdx][oldIdx]= DGRound3Message1 P2P from old party oldIdx to new party newIdx +// - OldR3Bcast[oldIdx] = DGRound3Message2 broadcast by old party oldIdx (decommitment) +// - NewR4P2P[newIdx][senderNewIdx] = DGRound4Message1 P2P from new party senderNewIdx to newIdx +// - NewR4Bcast[newIdx] = DGRound4Message2 broadcast by new party newIdx (ACK) +type ReshareFixture struct { + // Keygen outputs + OldKeys []keygen.LocalPartySaveData + + // Party IDs and contexts + OldPIDs tss.SortedPartyIDs + NewPIDs tss.SortedPartyIDs + OldCtx *tss.PeerContext + NewCtx *tss.PeerContext + + // Pre-params for new committee + PreParamsNew []keygen.LocalPreParams + + // Reshare states + OldStates []*ReshareState + NewStates []*ReshareState + + // Round 1: old committee broadcasts + OldR1Msgs []*tss.Message // [oldIdx] + + // Round 2: new committee broadcasts + NewR2Msg1s []*tss.Message // [newIdx] DGRound2Message1 (Pedersen params + proofs) + NewR2Msg2s []*tss.Message // [newIdx] DGRound2Message2 (ACK to old) + + // Round 3: old committee P2P + broadcast + OldR3P2P [][]*tss.Message // [newIdx][oldIdx] DGRound3Message1 + OldR3Bcast []*tss.Message // [oldIdx] DGRound3Message2 + + // Round 4: new committee P2P + broadcast + NewR4P2P [][]*tss.Message // [newIdx][senderNewIdx] DGRound4Message1 + NewR4Bcast []*tss.Message // [newIdx] DGRound4Message2 +} + +// doKeygen runs a full keygen for n parties with the given threshold and +// returns the keygen save data, party IDs, and peer context. +func doKeygen(t *testing.T, n, threshold int) ([]keygen.LocalPartySaveData, tss.SortedPartyIDs, *tss.PeerContext) { + t.Helper() + + preParams := testutil.LoadPreParams(t, n) + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + // Round 1 + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("doKeygen: Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + // Round 2 + r2P2P := make([][]*tss.Message, n) + r2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + r2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), states[i], r1) + if err != nil { + t.Fatalf("doKeygen: Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + r2Bcast[i] = pm + } else { + for _, to := range pm.To { + r2P2P[to.Index][i] = pm + } + } + } + r2P2P[i][i] = states[i].ExportR2P2PSelf() + if r2Bcast[i] == nil { + r2Bcast[i] = states[i].ExportR2BcastSelf() + } + } + + // Round 3 + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), states[i], r2P2P[i], r2Bcast) + if err != nil { + t.Fatalf("doKeygen: Round3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + + // Round 4 + keys := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), states[i], r3) + if err != nil { + t.Fatalf("doKeygen: Round4[%d]: %v", i, err) + } + keys[i] = *out.Save + } + + return keys, pIDs, peerCtx +} + +// setupReshareRound1 runs keygen(3) then reshare Round1 for 3 old -> 3 new +// (disjoint committees). Returns a fixture with OldR1Msgs populated. +// +// All proof flags (DLN, Mod, Fac) are disabled for speed in negative tests, +// since the proofs themselves are not the subject under test. +func setupReshareRound1(t *testing.T) *ReshareFixture { + t.Helper() + n := reshareN + threshold := reshareThreshold + + oldKeys, oldPIDs, oldCtx := doKeygen(t, n, threshold) + + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + + // Old committee: Round1 produces DGRound1Message broadcasts. + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("setupReshareRound1: ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + + // New committee: Round1 is a no-op, just creates state. + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("setupReshareRound1: ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + return &ReshareFixture{ + OldKeys: oldKeys, + OldPIDs: oldPIDs, + NewPIDs: newPIDs, + OldCtx: oldCtx, + NewCtx: newCtx, + PreParamsNew: preParamsNew, + OldStates: oldStates, + NewStates: newStates, + OldR1Msgs: oldR1Msgs, + } +} + +// setupThroughRound2 runs keygen + reshare Round1 + Round2. +// Returns a fixture with NewR2Msg1s and NewR2Msg2s populated. +func setupThroughRound2(t *testing.T) *ReshareFixture { + t.Helper() + n := reshareN + fix := setupReshareRound1(t) + + // New committee: Round2 produces DGRound2Message1 + DGRound2Message2. + fix.NewR2Msg1s = make([]*tss.Message, n) + fix.NewR2Msg2s = make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := ReshareRound2(fix.NewStates[i], fix.OldR1Msgs) + if err != nil { + t.Fatalf("setupThroughRound2: ReshareRound2(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound2Message1: + fix.NewR2Msg1s[i] = pm + case *DGRound2Message2: + fix.NewR2Msg2s[i] = pm + } + } + } + + // Old committee: Round2 is a no-op. + for i := 0; i < n; i++ { + _, err := ReshareRound2(fix.OldStates[i], fix.OldR1Msgs) + if err != nil { + t.Fatalf("setupThroughRound2: ReshareRound2(old)[%d]: %v", i, err) + } + } + + // Fill self-messages for new committee. + for i := 0; i < n; i++ { + if fix.NewR2Msg1s[i] == nil { + fix.NewR2Msg1s[i] = fix.NewStates[i].temp.dgRound2Message1s[i] + } + if fix.NewR2Msg2s[i] == nil { + fix.NewR2Msg2s[i] = fix.NewStates[i].temp.dgRound2Message2s[i] + } + } + + return fix +} + +// setupThroughRound3 runs keygen + reshare Rounds 1-3. +// Returns a fixture with OldR3P2P and OldR3Bcast populated. +func setupThroughRound3(t *testing.T) *ReshareFixture { + t.Helper() + n := reshareN + fix := setupThroughRound2(t) + + // Old committee: Round3 produces DGRound3Message1 (P2P) + DGRound3Message2 (broadcast). + fix.OldR3P2P = make([][]*tss.Message, n) + fix.OldR3Bcast = make([]*tss.Message, n) + for i := 0; i < n; i++ { + fix.OldR3P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound3(fix.OldStates[i], fix.NewR2Msg2s) + if err != nil { + t.Fatalf("setupThroughRound3: ReshareRound3(old)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound3Message1: + for _, to := range pm.To { + fix.OldR3P2P[to.Index][i] = pm + } + case *DGRound3Message2: + fix.OldR3Bcast[i] = pm + } + } + } + + // New committee: Round3 is a no-op. + for i := 0; i < n; i++ { + _, err := ReshareRound3(fix.NewStates[i], fix.NewR2Msg2s) + if err != nil { + t.Fatalf("setupThroughRound3: ReshareRound3(new)[%d]: %v", i, err) + } + } + + return fix +} + +// setupThroughRound4 runs keygen + reshare Rounds 1-4. +// Returns a fixture with NewR4P2P and NewR4Bcast populated. +func setupThroughRound4(t *testing.T) *ReshareFixture { + t.Helper() + n := reshareN + fix := setupThroughRound3(t) + + // New committee: Round4 produces DGRound4Message1 (P2P) + DGRound4Message2 (broadcast). + fix.NewR4P2P = make([][]*tss.Message, n) + fix.NewR4Bcast = make([]*tss.Message, n) + for i := 0; i < n; i++ { + fix.NewR4P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound4(context.Background(), fix.NewStates[i], fix.NewR2Msg1s, fix.OldR3P2P[i], fix.OldR3Bcast) + if err != nil { + t.Fatalf("setupThroughRound4: ReshareRound4(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound4Message1: + for _, to := range pm.To { + fix.NewR4P2P[to.Index][i] = pm + } + case *DGRound4Message2: + fix.NewR4Bcast[i] = pm + } + } + } + + // Old committee: Round4 is a no-op. + for i := 0; i < n; i++ { + _, err := ReshareRound4(context.Background(), fix.OldStates[i], fix.NewR2Msg1s, nil, nil) + if err != nil { + t.Fatalf("setupThroughRound4: ReshareRound4(old)[%d]: %v", i, err) + } + } + + // Fill self-messages. + for i := 0; i < n; i++ { + if fix.NewR4Bcast[i] == nil { + fix.NewR4Bcast[i] = fix.NewStates[i].temp.dgRound4Message2s[i] + } + } + + return fix +} + +// --------------------------------------------------------------------------- +// Clone helpers +// --------------------------------------------------------------------------- +// Each clone function creates a shallow copy of a *tss.Message with a +// deep-copied Content struct, so mutations in negative tests do not +// corrupt the original fixture messages. + +// cloneDGRound1Message clones a *tss.Message containing a DGRound1Message. +func cloneDGRound1Message(orig *tss.Message) *tss.Message { + c := orig.Content.(*DGRound1Message) + ssid := make([]byte, len(c.SSID)) + copy(ssid, c.SSID) + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: &DGRound1Message{ + ECDSAPub: c.ECDSAPub, // immutable ECPoint, no need to deep-copy + VCommitment: new(big.Int).Set(c.VCommitment), + SSID: ssid, + }, + } +} + +// cloneDGRound2Message1 clones a *tss.Message containing a DGRound2Message1. +// Proof objects (ModProof, DLNProof1, DLNProof2) are shared (not deep-copied) +// since they are large and typically not mutated in negative tests. The +// scalar fields (NTilde, H1, H2) are deep-copied. +func cloneDGRound2Message1(orig *tss.Message) *tss.Message { + c := orig.Content.(*DGRound2Message1) + var paiPK *paillier.PublicKey + if c.PaillierPK != nil { + paiPK = &paillier.PublicKey{N: new(big.Int).Set(c.PaillierPK.N)} + } + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: &DGRound2Message1{ + PaillierPK: paiPK, + NTilde: new(big.Int).Set(c.NTilde), + H1: new(big.Int).Set(c.H1), + H2: new(big.Int).Set(c.H2), + ModProof: c.ModProof, // shared reference + DLNProof1: c.DLNProof1, // shared reference + DLNProof2: c.DLNProof2, // shared reference + }, + } +} + +// cloneDGRound2Message2 clones a *tss.Message containing a DGRound2Message2. +func cloneDGRound2Message2(orig *tss.Message) *tss.Message { + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + IsToOldCommittee: orig.IsToOldCommittee, + Content: &DGRound2Message2{}, + } +} + +// cloneDGRound3Message1 clones a *tss.Message containing a DGRound3Message1. +func cloneDGRound3Message1(orig *tss.Message) *tss.Message { + c := orig.Content.(*DGRound3Message1) + rid := make([]byte, len(c.ReceiverID)) + copy(rid, c.ReceiverID) + return &tss.Message{ + From: orig.From, + To: orig.To, + Content: &DGRound3Message1{ + Share: new(big.Int).Set(c.Share), + ReceiverID: rid, + }, + } +} + +// cloneDGRound3Message2 clones a *tss.Message containing a DGRound3Message2. +func cloneDGRound3Message2(orig *tss.Message) *tss.Message { + c := orig.Content.(*DGRound3Message2) + dcmt := make(cmt.HashDeCommitment, len(c.VDeCommitment)) + for i, v := range c.VDeCommitment { + if v != nil { + dcmt[i] = new(big.Int).Set(v) + } + } + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + Content: &DGRound3Message2{ + VDeCommitment: dcmt, + }, + } +} + +// cloneDGRound4Message1 clones a *tss.Message containing a DGRound4Message1. +// The FacProof is shared (not deep-copied) since it is large. +func cloneDGRound4Message1(orig *tss.Message) *tss.Message { + c := orig.Content.(*DGRound4Message1) + rid := make([]byte, len(c.ReceiverID)) + copy(rid, c.ReceiverID) + return &tss.Message{ + From: orig.From, + To: orig.To, + Content: &DGRound4Message1{ + FacProof: c.FacProof, // shared reference + ReceiverID: rid, + }, + } +} + +// cloneDGRound4Message2 clones a *tss.Message containing a DGRound4Message2. +func cloneDGRound4Message2(orig *tss.Message) *tss.Message { + return &tss.Message{ + From: orig.From, + To: orig.To, + IsBroadcast: orig.IsBroadcast, + IsToOldAndNewCommittees: orig.IsToOldAndNewCommittees, + Content: &DGRound4Message2{}, + } +} + +// --------------------------------------------------------------------------- +// Slice-copy helpers +// --------------------------------------------------------------------------- +// These copy entire message slices so that a negative test can mutate one +// element without affecting the fixture. + +// copyR1Slice returns a deep-copied slice of DGRound1Message broadcasts. +func copyR1Slice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound1Message(m) + } + } + return out +} + +// copyR2Msg1Slice returns a deep-copied slice of DGRound2Message1 broadcasts. +func copyR2Msg1Slice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound2Message1(m) + } + } + return out +} + +// copyR2Msg2Slice returns a deep-copied slice of DGRound2Message2 broadcasts. +func copyR2Msg2Slice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound2Message2(m) + } + } + return out +} + +// copyR3P2PSlice returns a deep-copied slice of DGRound3Message1 P2P messages +// for a single receiver (i.e., fix.OldR3P2P[receiverNewIdx]). +func copyR3P2PSlice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound3Message1(m) + } + } + return out +} + +// copyR3BcastSlice returns a deep-copied slice of DGRound3Message2 broadcasts. +func copyR3BcastSlice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound3Message2(m) + } + } + return out +} + +// copyR4P2PSlice returns a deep-copied slice of DGRound4Message1 P2P messages +// for a single receiver (i.e., fix.NewR4P2P[receiverNewIdx]). +func copyR4P2PSlice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound4Message1(m) + } + } + return out +} + +// copyR4BcastSlice returns a deep-copied slice of DGRound4Message2 broadcasts. +func copyR4BcastSlice(msgs []*tss.Message) []*tss.Message { + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloneDGRound4Message2(m) + } + } + return out +} + +// --------------------------------------------------------------------------- +// Deep-clone helpers for proof objects (used when a negative test needs +// to corrupt a proof field without affecting the shared original). +// --------------------------------------------------------------------------- + +// cloneModProof returns a deep copy of a modproof.ProofMod. +func cloneModProof(orig *modproof.ProofMod) *modproof.ProofMod { + if orig == nil { + return nil + } + p := &modproof.ProofMod{ + W: new(big.Int).Set(orig.W), + A: new(big.Int).Set(orig.A), + B: new(big.Int).Set(orig.B), + } + for i := range orig.X { + if orig.X[i] != nil { + p.X[i] = new(big.Int).Set(orig.X[i]) + } + } + for i := range orig.Z { + if orig.Z[i] != nil { + p.Z[i] = new(big.Int).Set(orig.Z[i]) + } + } + return p +} + +// cloneDLNProof returns a deep copy of a dlnproof.Proof. +func cloneDLNProof(orig *dlnproof.Proof) *dlnproof.Proof { + if orig == nil { + return nil + } + p := &dlnproof.Proof{} + for i := range orig.Alpha { + if orig.Alpha[i] != nil { + p.Alpha[i] = new(big.Int).Set(orig.Alpha[i]) + } + } + for i := range orig.T { + if orig.T[i] != nil { + p.T[i] = new(big.Int).Set(orig.T[i]) + } + } + return p +} + +// cloneFacProof returns a deep copy of a facproof.ProofFac. +func cloneFacProof(orig *facproof.ProofFac) *facproof.ProofFac { + if orig == nil { + return nil + } + return &facproof.ProofFac{ + P: new(big.Int).Set(orig.P), + Q: new(big.Int).Set(orig.Q), + A: new(big.Int).Set(orig.A), + B: new(big.Int).Set(orig.B), + T: new(big.Int).Set(orig.T), + Sigma: new(big.Int).Set(orig.Sigma), + Z1: new(big.Int).Set(orig.Z1), + Z2: new(big.Int).Set(orig.Z2), + W1: new(big.Int).Set(orig.W1), + W2: new(big.Int).Set(orig.W2), + V: new(big.Int).Set(orig.V), + } +} + +// setupThroughRound3WithModProof is identical to setupThroughRound3 except +// that ModProof is NOT disabled on the new committee. This means Round2 +// generates real ModProof objects, allowing Round4 tests to exercise the +// proof verification path (lines 408-426 of round_fn.go). +func setupThroughRound3WithModProof(t *testing.T) *ReshareFixture { + t.Helper() + n := reshareN + threshold := reshareThreshold + + oldKeys, oldPIDs, oldCtx := doKeygen(t, n, threshold) + + newPIDs := tss.GenerateTestPartyIDs(n) + newCtx := tss.NewPeerContext(newPIDs) + + preParamsNew := testutil.LoadPreParamsFrom(t, n, n) + + oldStates := make([]*ReshareState, n) + newStates := make([]*ReshareState, n) + oldR1Msgs := make([]*tss.Message, n) + + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, oldPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + params.SetNoProofMod() + params.SetNoProofFac() + st, out, err := ReshareRound1(params, oldKeys[i], keygen.LocalPreParams{}) + if err != nil { + t.Fatalf("ReshareRound1(old)[%d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + oldR1Msgs[i] = out.Messages[0] + } + } + for i := 0; i < n; i++ { + params := tss.NewReSharingParameters(tss.S256(), oldCtx, newCtx, newPIDs[i], n, threshold, n, threshold) + params.SetNoProofDLN() + // NOTE: SetNoProofMod() is NOT called — ModProof will be generated in Round2. + params.SetNoProofFac() + st, _, err := ReshareRound1(params, keygen.NewLocalPartySaveData(n), preParamsNew[i]) + if err != nil { + t.Fatalf("ReshareRound1(new)[%d]: %v", i, err) + } + newStates[i] = st + } + + fix := &ReshareFixture{ + OldKeys: oldKeys, OldPIDs: oldPIDs, NewPIDs: newPIDs, + OldCtx: oldCtx, NewCtx: newCtx, PreParamsNew: preParamsNew, + OldStates: oldStates, NewStates: newStates, OldR1Msgs: oldR1Msgs, + } + + // Round2 + fix.NewR2Msg1s = make([]*tss.Message, n) + fix.NewR2Msg2s = make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := ReshareRound2(fix.NewStates[i], fix.OldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(new)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *DGRound2Message1: + fix.NewR2Msg1s[i] = msg + case *DGRound2Message2: + fix.NewR2Msg2s[i] = msg + } + } + } + for i := 0; i < n; i++ { + _, err := ReshareRound2(fix.OldStates[i], fix.OldR1Msgs) + if err != nil { + t.Fatalf("ReshareRound2(old)[%d]: %v", i, err) + } + } + for i := 0; i < n; i++ { + if fix.NewR2Msg1s[i] == nil { + fix.NewR2Msg1s[i] = fix.NewStates[i].temp.dgRound2Message1s[i] + } + if fix.NewR2Msg2s[i] == nil { + fix.NewR2Msg2s[i] = fix.NewStates[i].temp.dgRound2Message2s[i] + } + } + + // Round3 + fix.OldR3P2P = make([][]*tss.Message, n) + fix.OldR3Bcast = make([]*tss.Message, n) + for i := 0; i < n; i++ { + fix.OldR3P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := ReshareRound3(fix.OldStates[i], fix.NewR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(old)[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + switch pm.Content.(type) { + case *DGRound3Message1: + for _, to := range pm.To { + idx := newIndex2(to, newPIDs) + fix.OldR3P2P[idx][i] = pm + } + case *DGRound3Message2: + fix.OldR3Bcast[i] = pm + } + } + } + for i := 0; i < n; i++ { + _, err := ReshareRound3(fix.NewStates[i], fix.NewR2Msg2s) + if err != nil { + t.Fatalf("ReshareRound3(new)[%d]: %v", i, err) + } + } + + return fix +} + +// newIndex2 finds a party's index in a sorted ID list by key comparison. +func newIndex2(pid *tss.PartyID, pids tss.SortedPartyIDs) int { + for i, p := range pids { + if p.KeyInt().Cmp(pid.KeyInt()) == 0 { + return i + } + } + return -1 +} + +// requireCulprit unwraps a *tss.Error and asserts the culprit has the expected index. +func requireCulprit(t *testing.T, err error, wantIdx int) { + t.Helper() + tssErr := &tss.Error{} + if ok := errors.As(err, &tssErr); !ok { + t.Fatalf("expected *tss.Error, got %T", err) + } + culprits := tssErr.Culprits() + if len(culprits) != 1 || culprits[0].Index != wantIdx { + t.Fatalf("expected culprit index %d, got: %v", wantIdx, culprits) + } +} + +// Compile-time check: ensure all setup functions and clone helpers are usable. +var ( + _ = doKeygen + _ = setupReshareRound1 + _ = setupThroughRound2 + _ = setupThroughRound3 + _ = setupThroughRound3WithModProof + _ = setupThroughRound4 + _ = cloneDGRound1Message + _ = cloneDGRound2Message1 + _ = cloneDGRound2Message2 + _ = cloneDGRound3Message1 + _ = cloneDGRound3Message2 + _ = cloneDGRound4Message1 + _ = cloneDGRound4Message2 + _ = copyR1Slice + _ = copyR2Msg1Slice + _ = copyR2Msg2Slice + _ = copyR3P2PSlice + _ = copyR3BcastSlice + _ = copyR4P2PSlice + _ = copyR4BcastSlice + _ = cloneModProof + _ = cloneDLNProof + _ = cloneFacProof +) diff --git a/tss-lib/ecdsa/resharing/types.go b/tss-lib/ecdsa/resharing/types.go new file mode 100644 index 0000000..d2e31ad --- /dev/null +++ b/tss-lib/ecdsa/resharing/types.go @@ -0,0 +1,50 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TaskName identifies the resharing protocol in error messages. +const TaskName = "ecdsa-resharing" + +type ( + localMessageStore struct { + dgRound1Messages, + dgRound2Message1s, + dgRound2Message2s, + dgRound3Message1s, + dgRound3Message2s, + dgRound4Message1s, + dgRound4Message2s []*tss.Message + } + + localTempData struct { + localMessageStore + + // temp data (thrown away after rounds) + NewVs vss.Vs + NewShares vss.Shares + // [FORK] Store VSS polynomial coefficients for SNARK witness extraction. + Poly []*big.Int + VD cmt.HashDeCommitment + + // temporary storage of data that is persisted by the new party + // in round 5 if all "ACK" messages are received + newXi *big.Int + newKs []*big.Int + newBigXjs []*crypto.ECPoint // Xj to save in round 5 + + ssid []byte + ssidNonce *big.Int + } +) diff --git a/tss-lib/ecdsa/resharing/validate_basic_test.go b/tss-lib/ecdsa/resharing/validate_basic_test.go new file mode 100644 index 0000000..e284b12 --- /dev/null +++ b/tss-lib/ecdsa/resharing/validate_basic_test.go @@ -0,0 +1,349 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/paillier" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// helper returns a valid ECPoint on secp256k1 for use in tests. +func testECPoint() *crypto.ECPoint { + return crypto.ScalarBaseMult(tss.S256(), big.NewInt(42)) +} + +// helper returns a valid PaillierPK for use in tests. +func testPaillierPK() *paillier.PublicKey { + return &paillier.PublicKey{N: big.NewInt(100)} +} + +func TestDGRound1Message_ValidateBasic(t *testing.T) { + t.Parallel() + valid := &DGRound1Message{ + ECDSAPub: testECPoint(), + VCommitment: big.NewInt(1), + SSID: []byte("ssid"), + } + + tests := []struct { + name string + msg *DGRound1Message + want bool + }{ + {"valid", valid, true}, + {"nil_receiver", nil, false}, + {"ECDSAPub_nil", &DGRound1Message{ + ECDSAPub: nil, + VCommitment: big.NewInt(1), + SSID: []byte("ssid"), + }, false}, + {"VCommitment_nil", &DGRound1Message{ + ECDSAPub: testECPoint(), + VCommitment: nil, + SSID: []byte("ssid"), + }, false}, + {"VCommitment_zero", &DGRound1Message{ + ECDSAPub: testECPoint(), + VCommitment: big.NewInt(0), + SSID: []byte("ssid"), + }, false}, + {"VCommitment_negative", &DGRound1Message{ + ECDSAPub: testECPoint(), + VCommitment: big.NewInt(-1), + SSID: []byte("ssid"), + }, false}, + {"SSID_nil", &DGRound1Message{ + ECDSAPub: testECPoint(), + VCommitment: big.NewInt(1), + SSID: nil, + }, false}, + {"SSID_empty", &DGRound1Message{ + ECDSAPub: testECPoint(), + VCommitment: big.NewInt(1), + SSID: []byte{}, + }, false}, + {"all_zero_value", &DGRound1Message{}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDGRound2Message1_ValidateBasic(t *testing.T) { + t.Parallel() + valid := &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(5), + } + + tests := []struct { + name string + msg *DGRound2Message1 + want bool + }{ + {"valid", valid, true}, + {"valid_with_nil_optional_proofs", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(5), + ModProof: nil, + DLNProof1: nil, + DLNProof2: nil, + }, true}, + {"nil_receiver", nil, false}, + {"PaillierPK_nil", &DGRound2Message1{ + PaillierPK: nil, + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"PaillierPK_N_nil", &DGRound2Message1{ + PaillierPK: &paillier.PublicKey{N: nil}, + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"PaillierPK_N_zero", &DGRound2Message1{ + PaillierPK: &paillier.PublicKey{N: big.NewInt(0)}, + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"PaillierPK_N_negative", &DGRound2Message1{ + PaillierPK: &paillier.PublicKey{N: big.NewInt(-1)}, + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"NTilde_nil", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: nil, + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"NTilde_zero", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(0), + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"NTilde_negative", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(-1), + H1: big.NewInt(3), + H2: big.NewInt(5), + }, false}, + {"H1_nil", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: nil, + H2: big.NewInt(5), + }, false}, + {"H1_zero", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(0), + H2: big.NewInt(5), + }, false}, + {"H1_negative", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(-1), + H2: big.NewInt(5), + }, false}, + {"H2_nil", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: nil, + }, false}, + {"H2_zero", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(0), + }, false}, + {"H2_negative", &DGRound2Message1{ + PaillierPK: testPaillierPK(), + NTilde: big.NewInt(7), + H1: big.NewInt(3), + H2: big.NewInt(-1), + }, false}, + {"all_zero_value", &DGRound2Message1{}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDGRound2Message2_ValidateBasic(t *testing.T) { + t.Parallel() + tests := []struct { + name string + msg *DGRound2Message2 + want bool + }{ + {"valid", &DGRound2Message2{}, true}, + {"nil_receiver", nil, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDGRound3Message1_ValidateBasic(t *testing.T) { + t.Parallel() + valid := &DGRound3Message1{ + Share: big.NewInt(42), + ReceiverID: []byte("receiver"), + } + + tests := []struct { + name string + msg *DGRound3Message1 + want bool + }{ + {"valid", valid, true}, + {"nil_receiver", nil, false}, + {"Share_nil", &DGRound3Message1{ + Share: nil, + ReceiverID: []byte("receiver"), + }, false}, + {"Share_zero", &DGRound3Message1{ + Share: big.NewInt(0), + ReceiverID: []byte("receiver"), + }, false}, + {"Share_negative", &DGRound3Message1{ + Share: big.NewInt(-1), + ReceiverID: []byte("receiver"), + }, false}, + {"ReceiverID_nil", &DGRound3Message1{ + Share: big.NewInt(42), + ReceiverID: nil, + }, false}, + {"ReceiverID_empty", &DGRound3Message1{ + Share: big.NewInt(42), + ReceiverID: []byte{}, + }, false}, + {"all_zero_value", &DGRound3Message1{}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDGRound3Message2_ValidateBasic(t *testing.T) { + t.Parallel() + tests := []struct { + name string + msg *DGRound3Message2 + want bool + }{ + {"valid_2_elements", &DGRound3Message2{ + VDeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + }, true}, + {"valid_3_elements", &DGRound3Message2{ + VDeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, + }, true}, + {"nil_receiver", nil, false}, + {"VDeCommitment_nil", &DGRound3Message2{ + VDeCommitment: nil, + }, false}, + {"VDeCommitment_empty", &DGRound3Message2{ + VDeCommitment: cmt.HashDeCommitment{}, + }, false}, + {"VDeCommitment_1_element", &DGRound3Message2{ + VDeCommitment: cmt.HashDeCommitment{big.NewInt(1)}, + }, false}, + {"zero_value", &DGRound3Message2{}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDGRound4Message1_ValidateBasic(t *testing.T) { + t.Parallel() + tests := []struct { + name string + msg *DGRound4Message1 + want bool + }{ + {"valid", &DGRound4Message1{ReceiverID: []byte("receiver")}, true}, + {"valid_nil_FacProof", &DGRound4Message1{ + FacProof: nil, + ReceiverID: []byte("receiver"), + }, true}, + {"nil_receiver", nil, false}, + {"ReceiverID_nil", &DGRound4Message1{ + ReceiverID: nil, + }, false}, + {"ReceiverID_empty", &DGRound4Message1{ + ReceiverID: []byte{}, + }, false}, + {"zero_value", &DGRound4Message1{}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDGRound4Message2_ValidateBasic(t *testing.T) { + t.Parallel() + tests := []struct { + name string + msg *DGRound4Message2 + want bool + }{ + {"valid", &DGRound4Message2{}, true}, + {"nil_receiver", nil, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Fatalf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/tss-lib/ecdsa/signing/ecdsa-signing.pb.go b/tss-lib/ecdsa/signing/ecdsa-signing.pb.go deleted file mode 100644 index 4b8a55d..0000000 --- a/tss-lib/ecdsa/signing/ecdsa-signing.pb.go +++ /dev/null @@ -1,878 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.14.0 -// source: protob/ecdsa-signing.proto - -package signing - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// -// Represents a P2P message sent to each party during Round 1 of the ECDSA TSS signing protocol. -type SignRound1Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - C []byte `protobuf:"bytes,1,opt,name=c,proto3" json:"c,omitempty"` - RangeProofAlice [][]byte `protobuf:"bytes,2,rep,name=range_proof_alice,json=rangeProofAlice,proto3" json:"range_proof_alice,omitempty"` -} - -func (x *SignRound1Message1) Reset() { - *x = SignRound1Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound1Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound1Message1) ProtoMessage() {} - -func (x *SignRound1Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound1Message1.ProtoReflect.Descriptor instead. -func (*SignRound1Message1) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{0} -} - -func (x *SignRound1Message1) GetC() []byte { - if x != nil { - return x.C - } - return nil -} - -func (x *SignRound1Message1) GetRangeProofAlice() [][]byte { - if x != nil { - return x.RangeProofAlice - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 1 of the ECDSA TSS signing protocol. -type SignRound1Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` -} - -func (x *SignRound1Message2) Reset() { - *x = SignRound1Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound1Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound1Message2) ProtoMessage() {} - -func (x *SignRound1Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound1Message2.ProtoReflect.Descriptor instead. -func (*SignRound1Message2) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{1} -} - -func (x *SignRound1Message2) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -// -// Represents a P2P message sent to each party during Round 2 of the ECDSA TSS signing protocol. -type SignRound2Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - C1 []byte `protobuf:"bytes,1,opt,name=c1,proto3" json:"c1,omitempty"` - C2 []byte `protobuf:"bytes,2,opt,name=c2,proto3" json:"c2,omitempty"` - ProofBob [][]byte `protobuf:"bytes,3,rep,name=proof_bob,json=proofBob,proto3" json:"proof_bob,omitempty"` - ProofBobWc [][]byte `protobuf:"bytes,4,rep,name=proof_bob_wc,json=proofBobWc,proto3" json:"proof_bob_wc,omitempty"` -} - -func (x *SignRound2Message) Reset() { - *x = SignRound2Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound2Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound2Message) ProtoMessage() {} - -func (x *SignRound2Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound2Message.ProtoReflect.Descriptor instead. -func (*SignRound2Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{2} -} - -func (x *SignRound2Message) GetC1() []byte { - if x != nil { - return x.C1 - } - return nil -} - -func (x *SignRound2Message) GetC2() []byte { - if x != nil { - return x.C2 - } - return nil -} - -func (x *SignRound2Message) GetProofBob() [][]byte { - if x != nil { - return x.ProofBob - } - return nil -} - -func (x *SignRound2Message) GetProofBobWc() [][]byte { - if x != nil { - return x.ProofBobWc - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 3 of the ECDSA TSS signing protocol. -type SignRound3Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Theta []byte `protobuf:"bytes,1,opt,name=theta,proto3" json:"theta,omitempty"` -} - -func (x *SignRound3Message) Reset() { - *x = SignRound3Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound3Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound3Message) ProtoMessage() {} - -func (x *SignRound3Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound3Message.ProtoReflect.Descriptor instead. -func (*SignRound3Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{3} -} - -func (x *SignRound3Message) GetTheta() []byte { - if x != nil { - return x.Theta - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 4 of the ECDSA TSS signing protocol. -type SignRound4Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeCommitment [][]byte `protobuf:"bytes,1,rep,name=de_commitment,json=deCommitment,proto3" json:"de_commitment,omitempty"` - ProofAlphaX []byte `protobuf:"bytes,2,opt,name=proof_alpha_x,json=proofAlphaX,proto3" json:"proof_alpha_x,omitempty"` - ProofAlphaY []byte `protobuf:"bytes,3,opt,name=proof_alpha_y,json=proofAlphaY,proto3" json:"proof_alpha_y,omitempty"` - ProofT []byte `protobuf:"bytes,4,opt,name=proof_t,json=proofT,proto3" json:"proof_t,omitempty"` -} - -func (x *SignRound4Message) Reset() { - *x = SignRound4Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound4Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound4Message) ProtoMessage() {} - -func (x *SignRound4Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound4Message.ProtoReflect.Descriptor instead. -func (*SignRound4Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{4} -} - -func (x *SignRound4Message) GetDeCommitment() [][]byte { - if x != nil { - return x.DeCommitment - } - return nil -} - -func (x *SignRound4Message) GetProofAlphaX() []byte { - if x != nil { - return x.ProofAlphaX - } - return nil -} - -func (x *SignRound4Message) GetProofAlphaY() []byte { - if x != nil { - return x.ProofAlphaY - } - return nil -} - -func (x *SignRound4Message) GetProofT() []byte { - if x != nil { - return x.ProofT - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 5 of the ECDSA TSS signing protocol. -type SignRound5Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` -} - -func (x *SignRound5Message) Reset() { - *x = SignRound5Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound5Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound5Message) ProtoMessage() {} - -func (x *SignRound5Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound5Message.ProtoReflect.Descriptor instead. -func (*SignRound5Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{5} -} - -func (x *SignRound5Message) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 6 of the ECDSA TSS signing protocol. -type SignRound6Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeCommitment [][]byte `protobuf:"bytes,1,rep,name=de_commitment,json=deCommitment,proto3" json:"de_commitment,omitempty"` - ProofAlphaX []byte `protobuf:"bytes,2,opt,name=proof_alpha_x,json=proofAlphaX,proto3" json:"proof_alpha_x,omitempty"` - ProofAlphaY []byte `protobuf:"bytes,3,opt,name=proof_alpha_y,json=proofAlphaY,proto3" json:"proof_alpha_y,omitempty"` - ProofT []byte `protobuf:"bytes,4,opt,name=proof_t,json=proofT,proto3" json:"proof_t,omitempty"` - VProofAlphaX []byte `protobuf:"bytes,5,opt,name=v_proof_alpha_x,json=vProofAlphaX,proto3" json:"v_proof_alpha_x,omitempty"` - VProofAlphaY []byte `protobuf:"bytes,6,opt,name=v_proof_alpha_y,json=vProofAlphaY,proto3" json:"v_proof_alpha_y,omitempty"` - VProofT []byte `protobuf:"bytes,7,opt,name=v_proof_t,json=vProofT,proto3" json:"v_proof_t,omitempty"` - VProofU []byte `protobuf:"bytes,8,opt,name=v_proof_u,json=vProofU,proto3" json:"v_proof_u,omitempty"` -} - -func (x *SignRound6Message) Reset() { - *x = SignRound6Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound6Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound6Message) ProtoMessage() {} - -func (x *SignRound6Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound6Message.ProtoReflect.Descriptor instead. -func (*SignRound6Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{6} -} - -func (x *SignRound6Message) GetDeCommitment() [][]byte { - if x != nil { - return x.DeCommitment - } - return nil -} - -func (x *SignRound6Message) GetProofAlphaX() []byte { - if x != nil { - return x.ProofAlphaX - } - return nil -} - -func (x *SignRound6Message) GetProofAlphaY() []byte { - if x != nil { - return x.ProofAlphaY - } - return nil -} - -func (x *SignRound6Message) GetProofT() []byte { - if x != nil { - return x.ProofT - } - return nil -} - -func (x *SignRound6Message) GetVProofAlphaX() []byte { - if x != nil { - return x.VProofAlphaX - } - return nil -} - -func (x *SignRound6Message) GetVProofAlphaY() []byte { - if x != nil { - return x.VProofAlphaY - } - return nil -} - -func (x *SignRound6Message) GetVProofT() []byte { - if x != nil { - return x.VProofT - } - return nil -} - -func (x *SignRound6Message) GetVProofU() []byte { - if x != nil { - return x.VProofU - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 7 of the ECDSA TSS signing protocol. -type SignRound7Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` -} - -func (x *SignRound7Message) Reset() { - *x = SignRound7Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound7Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound7Message) ProtoMessage() {} - -func (x *SignRound7Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound7Message.ProtoReflect.Descriptor instead. -func (*SignRound7Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{7} -} - -func (x *SignRound7Message) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 8 of the ECDSA TSS signing protocol. -type SignRound8Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeCommitment [][]byte `protobuf:"bytes,1,rep,name=de_commitment,json=deCommitment,proto3" json:"de_commitment,omitempty"` -} - -func (x *SignRound8Message) Reset() { - *x = SignRound8Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound8Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound8Message) ProtoMessage() {} - -func (x *SignRound8Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound8Message.ProtoReflect.Descriptor instead. -func (*SignRound8Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{8} -} - -func (x *SignRound8Message) GetDeCommitment() [][]byte { - if x != nil { - return x.DeCommitment - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 9 of the ECDSA TSS signing protocol. -type SignRound9Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - S []byte `protobuf:"bytes,1,opt,name=s,proto3" json:"s,omitempty"` -} - -func (x *SignRound9Message) Reset() { - *x = SignRound9Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_ecdsa_signing_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound9Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound9Message) ProtoMessage() {} - -func (x *SignRound9Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_ecdsa_signing_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound9Message.ProtoReflect.Descriptor instead. -func (*SignRound9Message) Descriptor() ([]byte, []int) { - return file_protob_ecdsa_signing_proto_rawDescGZIP(), []int{9} -} - -func (x *SignRound9Message) GetS() []byte { - if x != nil { - return x.S - } - return nil -} - -var File_protob_ecdsa_signing_proto protoreflect.FileDescriptor - -var file_protob_ecdsa_signing_proto_rawDesc = []byte{ - 0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x62, 0x69, - 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x63, 0x64, - 0x73, 0x61, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x4e, 0x0a, 0x12, 0x53, 0x69, - 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, - 0x12, 0x0c, 0x0a, 0x01, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x63, 0x12, 0x2a, - 0x0a, 0x11, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, - 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0f, 0x72, 0x61, 0x6e, 0x67, 0x65, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x69, 0x63, 0x65, 0x22, 0x34, 0x0a, 0x12, 0x53, 0x69, - 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, - 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, - 0x22, 0x72, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x63, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x02, 0x63, 0x31, 0x12, 0x0e, 0x0a, 0x02, 0x63, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x02, 0x63, 0x32, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x62, - 0x6f, 0x62, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, - 0x6f, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x62, 0x6f, 0x62, 0x5f, - 0x77, 0x63, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, - 0x6f, 0x62, 0x57, 0x63, 0x22, 0x29, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x33, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x68, 0x65, - 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x68, 0x65, 0x74, 0x61, 0x22, - 0x99, 0x01, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x34, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x58, 0x12, 0x22, - 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, 0x68, - 0x61, 0x59, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x22, 0x33, 0x0a, 0x11, 0x53, - 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x35, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, - 0x22, 0x9f, 0x02, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x36, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, - 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x70, - 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x58, 0x12, - 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, - 0x68, 0x61, 0x59, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x12, 0x25, 0x0a, 0x0f, - 0x76, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x78, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, - 0x68, 0x61, 0x58, 0x12, 0x25, 0x0a, 0x0f, 0x76, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x50, - 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x59, 0x12, 0x1a, 0x0a, 0x09, 0x76, 0x5f, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x76, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x12, 0x1a, 0x0a, 0x09, 0x76, 0x5f, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x5f, 0x75, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x76, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x55, 0x22, 0x33, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x37, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, - 0x6f, 0x75, 0x6e, 0x64, 0x38, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, - 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x22, 0x21, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x39, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0c, 0x0a, 0x01, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x01, 0x73, 0x42, 0x0f, 0x5a, 0x0d, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2f, 0x73, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_protob_ecdsa_signing_proto_rawDescOnce sync.Once - file_protob_ecdsa_signing_proto_rawDescData = file_protob_ecdsa_signing_proto_rawDesc -) - -func file_protob_ecdsa_signing_proto_rawDescGZIP() []byte { - file_protob_ecdsa_signing_proto_rawDescOnce.Do(func() { - file_protob_ecdsa_signing_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_ecdsa_signing_proto_rawDescData) - }) - return file_protob_ecdsa_signing_proto_rawDescData -} - -var file_protob_ecdsa_signing_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_protob_ecdsa_signing_proto_goTypes = []interface{}{ - (*SignRound1Message1)(nil), // 0: binance.tsslib.ecdsa.signing.SignRound1Message1 - (*SignRound1Message2)(nil), // 1: binance.tsslib.ecdsa.signing.SignRound1Message2 - (*SignRound2Message)(nil), // 2: binance.tsslib.ecdsa.signing.SignRound2Message - (*SignRound3Message)(nil), // 3: binance.tsslib.ecdsa.signing.SignRound3Message - (*SignRound4Message)(nil), // 4: binance.tsslib.ecdsa.signing.SignRound4Message - (*SignRound5Message)(nil), // 5: binance.tsslib.ecdsa.signing.SignRound5Message - (*SignRound6Message)(nil), // 6: binance.tsslib.ecdsa.signing.SignRound6Message - (*SignRound7Message)(nil), // 7: binance.tsslib.ecdsa.signing.SignRound7Message - (*SignRound8Message)(nil), // 8: binance.tsslib.ecdsa.signing.SignRound8Message - (*SignRound9Message)(nil), // 9: binance.tsslib.ecdsa.signing.SignRound9Message -} -var file_protob_ecdsa_signing_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_protob_ecdsa_signing_proto_init() } -func file_protob_ecdsa_signing_proto_init() { - if File_protob_ecdsa_signing_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_ecdsa_signing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound1Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound1Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound2Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound3Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound4Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound5Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound6Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound7Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound8Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_ecdsa_signing_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound9Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_ecdsa_signing_proto_rawDesc, - NumEnums: 0, - NumMessages: 10, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_ecdsa_signing_proto_goTypes, - DependencyIndexes: file_protob_ecdsa_signing_proto_depIdxs, - MessageInfos: file_protob_ecdsa_signing_proto_msgTypes, - }.Build() - File_protob_ecdsa_signing_proto = out.File - file_protob_ecdsa_signing_proto_rawDesc = nil - file_protob_ecdsa_signing_proto_goTypes = nil - file_protob_ecdsa_signing_proto_depIdxs = nil -} diff --git a/tss-lib/ecdsa/signing/finalize.go b/tss-lib/ecdsa/signing/finalize.go deleted file mode 100644 index 5523ebe..0000000 --- a/tss-lib/ecdsa/signing/finalize.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "crypto/ecdsa" - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *finalization) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 10 - round.started = true - round.resetOK() - - sumS := round.temp.si - modN := common.ModInt(round.Params().EC().Params().N) - - for j := range round.Parties().IDs() { - round.ok[j] = true - if j == round.PartyID().Index { - continue - } - r9msg := round.temp.signRound9Messages[j].Content().(*SignRound9Message) - sumS = modN.Add(sumS, r9msg.UnmarshalS()) - } - - recid := 0 - // byte v = if(R.X > curve.N) then 2 else 0) | (if R.Y.IsEven then 0 else 1); - if round.temp.rx.Cmp(round.Params().EC().Params().N) > 0 { - recid = 2 - } - if round.temp.ry.Bit(0) != 0 { - recid |= 1 - } - - // This is copied from: - // https://github.com/btcsuite/btcd/blob/c26ffa870fd817666a857af1bf6498fabba1ffe3/btcec/signature.go#L442-L444 - // This is needed because of tendermint checks here: - // https://github.com/tendermint/tendermint/blob/d9481e3648450cb99e15c6a070c1fb69aa0c255b/crypto/secp256k1/secp256k1_nocgo.go#L43-L47 - secp256k1halfN := new(big.Int).Rsh(round.Params().EC().Params().N, 1) - if sumS.Cmp(secp256k1halfN) > 0 { - sumS.Sub(round.Params().EC().Params().N, sumS) - recid ^= 1 - } - - // save the signature for final output - bitSizeInBytes := round.Params().EC().Params().BitSize / 8 - round.data.R = padToLengthBytesInPlace(round.temp.rx.Bytes(), bitSizeInBytes) - round.data.S = padToLengthBytesInPlace(sumS.Bytes(), bitSizeInBytes) - round.data.Signature = append(round.data.R, round.data.S...) - round.data.SignatureRecovery = []byte{byte(recid)} - if round.temp.fullBytesLen == 0 { - round.data.M = round.temp.m.Bytes() - } else { - var mBytes = make([]byte, round.temp.fullBytesLen) - round.temp.m.FillBytes(mBytes) - round.data.M = mBytes - } - - pk := ecdsa.PublicKey{ - Curve: round.Params().EC(), - X: round.key.ECDSAPub.X(), - Y: round.key.ECDSAPub.Y(), - } - - ok := ecdsa.Verify(&pk, round.data.M, round.temp.rx, sumS) - if !ok { - return round.WrapError(fmt.Errorf("signature verification failed")) - } - - round.end <- round.data - - return nil -} - -func (round *finalization) CanAccept(msg tss.ParsedMessage) bool { - // not expecting any incoming messages in this round - return false -} - -func (round *finalization) Update() (bool, *tss.Error) { - // not expecting any incoming messages in this round - return false, nil -} - -func (round *finalization) NextRound() tss.Round { - return nil // finished! -} - -func padToLengthBytesInPlace(src []byte, length int) []byte { - oriLen := len(src) - if oriLen < length { - for i := 0; i < length-oriLen; i++ { - src = append([]byte{0}, src...) - } - } - return src -} diff --git a/tss-lib/ecdsa/signing/finalize_negative_test.go b/tss-lib/ecdsa/signing/finalize_negative_test.go new file mode 100644 index 0000000..089bdbf --- /dev/null +++ b/tss-lib/ecdsa/signing/finalize_negative_test.go @@ -0,0 +1,127 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestSignFinalizeRejectsNegativeSi verifies that SignFinalize rejects a +// Round 9 message whose si value is negative. This exercises the +// sj.Sign() < 0 branch at round_fn.go:701. +func TestSignFinalizeRejectsNegativeSi(t *testing.T) { + f := setupThroughRound9(t) + r9 := CloneBcastSlice(f.R9Bcast, CloneR9BcastMsg) + + // Corrupt party 1's si to be negative. + r9[1].Content.(*SignRound9Message).S = new(big.Int).Neg(big.NewInt(42)) + + _, err := SignFinalize(f.States[0], r9) + if err == nil { + t.Fatal("expected error for negative si, got nil") + } + if !strings.Contains(err.Error(), "outside [0, N)") { + t.Fatalf("unexpected error message: %v", err) + } + t.Logf("correctly rejected negative si: %v", err) +} + +// TestSignFinalizeRejectsOversizedSi verifies that SignFinalize rejects a +// Round 9 message whose si value equals or exceeds the curve order N. +// This exercises the sj.Cmp(N) >= 0 branch at round_fn.go:701. +func TestSignFinalizeRejectsOversizedSi(t *testing.T) { + f := setupThroughRound9(t) + N := tss.S256().Params().N + + // Sub-test: si == N (exactly equal to curve order). + t.Run("si_equals_N", func(t *testing.T) { + r9 := CloneBcastSlice(f.R9Bcast, CloneR9BcastMsg) + r9[1].Content.(*SignRound9Message).S = new(big.Int).Set(N) + + _, err := SignFinalize(f.States[0], r9) + if err == nil { + t.Fatal("expected error for si == N, got nil") + } + if !strings.Contains(err.Error(), "outside [0, N)") { + t.Fatalf("unexpected error message: %v", err) + } + }) + + // Sub-test: si == N + 1 (exceeds curve order). + t.Run("si_exceeds_N", func(t *testing.T) { + r9 := CloneBcastSlice(f.R9Bcast, CloneR9BcastMsg) + r9[1].Content.(*SignRound9Message).S = new(big.Int).Add(N, big.NewInt(1)) + + _, err := SignFinalize(f.States[0], r9) + if err == nil { + t.Fatal("expected error for si > N, got nil") + } + if !strings.Contains(err.Error(), "outside [0, N)") { + t.Fatalf("unexpected error message: %v", err) + } + }) +} + +// TestSignFinalizeRejectsZeroSumS verifies that SignFinalize rejects when +// all si shares sum to zero mod N. This exercises the sumS.Sign() == 0 +// guard at round_fn.go:706-707. +func TestSignFinalizeRejectsZeroSumS(t *testing.T) { + f := setupThroughRound9(t) + N := tss.S256().Params().N + r9 := CloneBcastSlice(f.R9Bcast, CloneR9BcastMsg) + + // Compute the sum of si for parties 0 and 1, then set party 2's si + // to the additive inverse so the total is zero mod N. + s0 := f.States[0].temp.si + s1 := r9[1].Content.(*SignRound9Message).S + sumOthers := new(big.Int).Add(s0, s1) + sumOthers.Mod(sumOthers, N) + // party 2's si = N - sumOthers (i.e., -sumOthers mod N) + r9[2].Content.(*SignRound9Message).S = new(big.Int).Sub(N, sumOthers) + + _, err := SignFinalize(f.States[0], r9) + if err == nil { + t.Fatal("expected error for zero accumulated S, got nil") + } + if !strings.Contains(err.Error(), "accumulated S is zero") { + t.Fatalf("unexpected error message: %v", err) + } + t.Logf("correctly rejected zero sum S: %v", err) +} + +// TestSignFinalizeRejectsCorruptedSi verifies that SignFinalize rejects a +// Round 9 message whose si is a valid-range value but produces an +// incorrect aggregate S, causing ECDSA signature verification to fail. +// This exercises the ecdsa.Verify failure branch at round_fn.go:743-744. +func TestSignFinalizeRejectsCorruptedSi(t *testing.T) { + f := setupThroughRound9(t) + N := tss.S256().Params().N + r9 := CloneBcastSlice(f.R9Bcast, CloneR9BcastMsg) + + // Corrupt party 2's si to a different valid value (si + 1 mod N). + // This keeps si in [1, N-1] but changes the aggregate S, so the + // final ECDSA verification must fail. + r9msg := r9[2].Content.(*SignRound9Message) + corrupted := new(big.Int).Add(r9msg.S, big.NewInt(1)) + corrupted.Mod(corrupted, N) + // Ensure the corrupted value is not zero (would hit a different path). + if corrupted.Sign() == 0 { + corrupted.SetInt64(1) + } + r9msg.S = corrupted + + _, err := SignFinalize(f.States[0], r9) + if err == nil { + t.Fatal("expected error for corrupted si, got nil") + } + if !strings.Contains(err.Error(), "signature verification failed") { + t.Fatalf("unexpected error message: %v", err) + } + t.Logf("correctly rejected corrupted si: %v", err) +} diff --git a/tss-lib/ecdsa/signing/key_derivation_test.go b/tss-lib/ecdsa/signing/key_derivation_test.go new file mode 100644 index 0000000..0255349 --- /dev/null +++ b/tss-lib/ecdsa/signing/key_derivation_test.go @@ -0,0 +1,77 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "crypto/ecdsa" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestUpdatePublicKeyAndAdjustBigXj(t *testing.T) { + ec := tss.S256() + + // Create a fake key share with a known public key. + privKey := big.NewInt(42) + pub := crypto.ScalarBaseMult(ec, privKey) + bigXj := []*crypto.ECPoint{pub} + + save := keygen.LocalPartySaveData{ + ECDSAPub: pub, + BigXj: bigXj, + } + + delta := big.NewInt(7) + deltaG := crypto.ScalarBaseMult(ec, delta) + + // New public key = pub + delta*G + newPub, err := pub.Add(deltaG) + if err != nil { + t.Fatalf("Add: %v", err) + } + extPub := &ecdsa.PublicKey{ + Curve: ec, + X: newPub.X(), + Y: newPub.Y(), + } + + keys := []keygen.LocalPartySaveData{save} + err = UpdatePublicKeyAndAdjustBigXj(delta, keys, extPub, ec) + if err != nil { + t.Fatalf("UpdatePublicKeyAndAdjustBigXj: %v", err) + } + + // ECDSAPub should now be newPub. + if !keys[0].ECDSAPub.Equals(newPub) { + t.Fatal("ECDSAPub not updated") + } + // BigXj[0] should be original + delta*G. + expectedBigXj, err := pub.Add(deltaG) + if err != nil { + t.Fatalf("expected Add: %v", err) + } + if !keys[0].BigXj[0].Equals(expectedBigXj) { + t.Fatal("BigXj[0] not adjusted") + } +} + +func TestUpdatePublicKeyAndAdjustBigXjZeroDelta(t *testing.T) { + ec := tss.S256() + pub := crypto.ScalarBaseMult(ec, big.NewInt(42)) + save := keygen.LocalPartySaveData{ + ECDSAPub: pub, + BigXj: []*crypto.ECPoint{pub}, + } + extPub := &ecdsa.PublicKey{Curve: ec, X: pub.X(), Y: pub.Y()} + + err := UpdatePublicKeyAndAdjustBigXj(big.NewInt(0), []keygen.LocalPartySaveData{save}, extPub, ec) + if err == nil { + t.Fatal("expected error for zero delta") + } +} diff --git a/tss-lib/ecdsa/signing/key_derivation_util.go b/tss-lib/ecdsa/signing/key_derivation_util.go index 6cf2934..4f8c352 100644 --- a/tss-lib/ecdsa/signing/key_derivation_util.go +++ b/tss-lib/ecdsa/signing/key_derivation_util.go @@ -1,21 +1,29 @@ -// Copyright © 2021 Swingby +// Copyright (c) 2021 Swingby +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package signing import ( "crypto/ecdsa" "crypto/elliptic" + "errors" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/ckd" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - - "github.com/btcsuite/btcd/chaincfg" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" ) +// UpdatePublicKeyAndAdjustBigXj adjusts the distributed public key and BigXj shares for BIP-32 key derivation. func UpdatePublicKeyAndAdjustBigXj(keyDerivationDelta *big.Int, keys []keygen.LocalPartySaveData, extendedChildPk *ecdsa.PublicKey, ec elliptic.Curve) error { + // [FORK] Guard keyDerivationDelta=0: ScalarBaseMult(0) panics (identity point). + // keyDerivationDelta is a sum of BIP-32 IL values mod q; each is validated non-zero + // individually, but their sum mod q could be 0 with probability ~2^-256. + if keyDerivationDelta.Sign() == 0 { + return errors.New("UpdatePublicKeyAndAdjustBigXj: keyDerivationDelta is zero") + } var err error gDelta := crypto.ScalarBaseMult(ec, keyDerivationDelta) for k := range keys { @@ -27,7 +35,7 @@ func UpdatePublicKeyAndAdjustBigXj(keyDerivationDelta *big.Int, keys []keygen.Lo // Suppose X_j has shamir shares X_j0, X_j1, ..., X_jn // So X_j + D has shamir shares X_j0 + D, X_j1 + D, ..., X_jn + D for j := range keys[k].BigXj { - keys[k].BigXj[j], err = keys[k].BigXj[j].Add(gDelta) + keys[k].BigXj[j], err = keys[k].BigXj[j].Add(gDelta) //nolint:gosec // k bounded by range keys if err != nil { common.Logger.Errorf("error in delta operation") return err @@ -36,24 +44,3 @@ func UpdatePublicKeyAndAdjustBigXj(keyDerivationDelta *big.Int, keys []keygen.Lo } return nil } - -func derivingPubkeyFromPath(masterPub *crypto.ECPoint, chainCode []byte, path []uint32, ec elliptic.Curve) (*big.Int, *ckd.ExtendedKey, error) { - // build ecdsa key pair - pk := ecdsa.PublicKey{ - Curve: ec, - X: masterPub.X(), - Y: masterPub.Y(), - } - - net := &chaincfg.MainNetParams - extendedParentPk := &ckd.ExtendedKey{ - PublicKey: pk, - Depth: 0, - ChildIndex: 0, - ChainCode: chainCode[:], - ParentFP: []byte{0x00, 0x00, 0x00, 0x00}, - Version: net.HDPrivateKeyID[:], - } - - return ckd.DeriveChildKeyFromHierarchy(path, extendedParentPk, ec.Params().N, ec) -} diff --git a/tss-lib/ecdsa/signing/local_party.go b/tss-lib/ecdsa/signing/local_party.go deleted file mode 100644 index cf34cf5..0000000 --- a/tss-lib/ecdsa/signing/local_party.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/mta" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Implements Party -// Implements Stringer -var ( - _ tss.Party = (*LocalParty)(nil) - _ fmt.Stringer = (*LocalParty)(nil) -) - -type ( - LocalParty struct { - *tss.BaseParty - params *tss.Parameters - - keys keygen.LocalPartySaveData - temp localTempData - data *common.SignatureData - - // outbound messaging - out chan<- tss.Message - end chan<- *common.SignatureData - } - - localMessageStore struct { - signRound1Message1s, - signRound1Message2s, - signRound2Messages, - signRound3Messages, - signRound4Messages, - signRound5Messages, - signRound6Messages, - signRound7Messages, - signRound8Messages, - signRound9Messages []tss.ParsedMessage - } - - localTempData struct { - localMessageStore - - // temp data (thrown away after sign) / round 1 - w, - m, - k, - theta, - thetaInverse, - sigma, - keyDerivationDelta, - gamma *big.Int - fullBytesLen int - cis []*big.Int - bigWs []*crypto.ECPoint - pointGamma *crypto.ECPoint - deCommit cmt.HashDeCommitment - - // round 2 - betas, // return value of Bob_mid - c1jis, - c2jis, - vs []*big.Int // return value of Bob_mid_wc - pi1jis []*mta.ProofBob - pi2jis []*mta.ProofBobWC - - // round 5 - li, - si, - rx, - ry, - roi *big.Int - bigR, - bigAi, - bigVi *crypto.ECPoint - DPower cmt.HashDeCommitment - - // round 7 - Ui, - Ti *crypto.ECPoint - DTelda cmt.HashDeCommitment - - ssidNonce *big.Int - ssid []byte - } -) - -func NewLocalParty( - msg *big.Int, - params *tss.Parameters, - key keygen.LocalPartySaveData, - out chan<- tss.Message, - end chan<- *common.SignatureData, - fullBytesLen ...int) tss.Party { - return NewLocalPartyWithKDD(msg, params, key, nil, out, end, fullBytesLen...) -} - -// NewLocalPartyWithKDD returns a party with key derivation delta for HD support -func NewLocalPartyWithKDD( - msg *big.Int, - params *tss.Parameters, - key keygen.LocalPartySaveData, - keyDerivationDelta *big.Int, - out chan<- tss.Message, - end chan<- *common.SignatureData, - fullBytesLen ...int, -) tss.Party { - partyCount := len(params.Parties().IDs()) - p := &LocalParty{ - BaseParty: new(tss.BaseParty), - params: params, - keys: keygen.BuildLocalSaveDataSubset(key, params.Parties().IDs()), - temp: localTempData{}, - data: &common.SignatureData{}, - out: out, - end: end, - } - // msgs init - p.temp.signRound1Message1s = make([]tss.ParsedMessage, partyCount) - p.temp.signRound1Message2s = make([]tss.ParsedMessage, partyCount) - p.temp.signRound2Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound3Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound4Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound5Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound6Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound7Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound8Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound9Messages = make([]tss.ParsedMessage, partyCount) - // temp data init - p.temp.keyDerivationDelta = keyDerivationDelta - p.temp.m = msg - if len(fullBytesLen) > 0 { - p.temp.fullBytesLen = fullBytesLen[0] - } else { - p.temp.fullBytesLen = 0 - } - p.temp.cis = make([]*big.Int, partyCount) - p.temp.bigWs = make([]*crypto.ECPoint, partyCount) - p.temp.betas = make([]*big.Int, partyCount) - p.temp.c1jis = make([]*big.Int, partyCount) - p.temp.c2jis = make([]*big.Int, partyCount) - p.temp.pi1jis = make([]*mta.ProofBob, partyCount) - p.temp.pi2jis = make([]*mta.ProofBobWC, partyCount) - p.temp.vs = make([]*big.Int, partyCount) - return p -} - -func (p *LocalParty) FirstRound() tss.Round { - return newRound1(p.params, &p.keys, p.data, &p.temp, p.out, p.end) -} - -func (p *LocalParty) Start() *tss.Error { - return tss.BaseStart(p, TaskName, func(round tss.Round) *tss.Error { - round1, ok := round.(*round1) - if !ok { - return round.WrapError(errors.New("unable to Start(). party is in an unexpected round")) - } - if err := round1.prepare(); err != nil { - return round.WrapError(err) - } - return nil - }) -} - -func (p *LocalParty) Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) { - return tss.BaseUpdate(p, msg, TaskName) -} - -func (p *LocalParty) UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (bool, *tss.Error) { - msg, err := tss.ParseWireMessage(wireBytes, from, isBroadcast) - if err != nil { - return false, p.WrapError(err) - } - return p.Update(msg) -} - -func (p *LocalParty) ValidateMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - if ok, err := p.BaseParty.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - // check that the message's "from index" will fit into the array - if maxFromIdx := len(p.params.Parties().IDs()) - 1; maxFromIdx < msg.GetFrom().Index { - return false, p.WrapError(fmt.Errorf("received msg with a sender index too great (%d <= %d)", - maxFromIdx, msg.GetFrom().Index), msg.GetFrom()) - } - return true, nil -} - -func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - // ValidateBasic is cheap; double-check the message here in case the public StoreMessage was called externally - if ok, err := p.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - fromPIdx := msg.GetFrom().Index - - // switch/case is necessary to store any messages beyond current round - // this does not handle message replays. we expect the caller to apply replay and spoofing protection. - switch msg.Content().(type) { - case *SignRound1Message1: - p.temp.signRound1Message1s[fromPIdx] = msg - case *SignRound1Message2: - p.temp.signRound1Message2s[fromPIdx] = msg - case *SignRound2Message: - p.temp.signRound2Messages[fromPIdx] = msg - case *SignRound3Message: - p.temp.signRound3Messages[fromPIdx] = msg - case *SignRound4Message: - p.temp.signRound4Messages[fromPIdx] = msg - case *SignRound5Message: - p.temp.signRound5Messages[fromPIdx] = msg - case *SignRound6Message: - p.temp.signRound6Messages[fromPIdx] = msg - case *SignRound7Message: - p.temp.signRound7Messages[fromPIdx] = msg - case *SignRound8Message: - p.temp.signRound8Messages[fromPIdx] = msg - case *SignRound9Message: - p.temp.signRound9Messages[fromPIdx] = msg - default: // unrecognised message, just ignore! - common.Logger.Warningf("unrecognised message ignored: %v", msg) - return false, nil - } - return true, nil -} - -func (p *LocalParty) PartyID() *tss.PartyID { - return p.params.PartyID() -} - -func (p *LocalParty) String() string { - return fmt.Sprintf("id: %s, %s", p.PartyID(), p.BaseParty.String()) -} diff --git a/tss-lib/ecdsa/signing/local_party_test.go b/tss-lib/ecdsa/signing/local_party_test.go deleted file mode 100644 index e382926..0000000 --- a/tss-lib/ecdsa/signing/local_party_test.go +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "crypto/ecdsa" - "crypto/rand" - "encoding/hex" - "fmt" - "math/big" - "runtime" - "sync/atomic" - "testing" - - "github.com/btcsuite/btcd/btcec/v2" - "github.com/ipfs/go-log" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - testParticipants = test.TestParticipants - testThreshold = test.TestThreshold -) - -func setUp(level string) { - if err := log.SetLogLevel("tss-lib", level); err != nil { - panic(err) - } -} - -func TestE2EConcurrent(t *testing.T) { - setUp("info") - threshold := testThreshold - - // PHASE: load keygen fixtures - keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) - assert.NoError(t, err, "should load keygen fixtures") - assert.Equal(t, testThreshold+1, len(keys)) - assert.Equal(t, testThreshold+1, len(signPIDs)) - - // PHASE: signing - // use a shuffled selection of the list of parties for this test - p2pCtx := tss.NewPeerContext(signPIDs) - parties := make([]*LocalParty, 0, len(signPIDs)) - - errCh := make(chan *tss.Error, len(signPIDs)) - outCh := make(chan tss.Message, len(signPIDs)) - endCh := make(chan *common.SignatureData, len(signPIDs)) - - updater := test.SharedPartyUpdater - // init the parties - for i := 0; i < len(signPIDs); i++ { - params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - P := NewLocalParty(big.NewInt(42), params, keys[i], outCh, endCh).(*LocalParty) - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - var ended int32 -signing: - for { - fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break signing - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case <-endCh: - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { - t.Logf("Done. Received signature data from %d participants", ended) - R := parties[0].temp.bigR - r := parties[0].temp.rx - fmt.Printf("sign result: R(%s, %s), r=%s\n", R.X().String(), R.Y().String(), r.String()) - - modN := common.ModInt(tss.S256().Params().N) - - // BEGIN check s correctness - sumS := big.NewInt(0) - for _, p := range parties { - sumS = modN.Add(sumS, p.temp.si) - } - fmt.Printf("S: %s\n", sumS.String()) - // END check s correctness - - // BEGIN ECDSA verify - pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y() - pk := ecdsa.PublicKey{ - Curve: tss.EC(), - X: pkX, - Y: pkY, - } - ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS) - assert.True(t, ok, "ecdsa verify must pass") - t.Log("ECDSA signing test done.") - // END ECDSA verify - - break signing - } - } - } -} - -func TestE2EConcurrentWithLeadingZeroInMSG(t *testing.T) { - setUp("info") - threshold := testThreshold - - // PHASE: load keygen fixtures - keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) - assert.NoError(t, err, "should load keygen fixtures") - assert.Equal(t, testThreshold+1, len(keys)) - assert.Equal(t, testThreshold+1, len(signPIDs)) - - // PHASE: signing - // use a shuffled selection of the list of parties for this test - p2pCtx := tss.NewPeerContext(signPIDs) - parties := make([]*LocalParty, 0, len(signPIDs)) - - errCh := make(chan *tss.Error, len(signPIDs)) - outCh := make(chan tss.Message, len(signPIDs)) - endCh := make(chan *common.SignatureData, len(signPIDs)) - - updater := test.SharedPartyUpdater - msgData, _ := hex.DecodeString("00f163ee51bcaeff9cdff5e0e3c1a646abd19885fffbab0b3b4236e0cf95c9f5") - // init the parties - for i := 0; i < len(signPIDs); i++ { - params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - P := NewLocalParty(new(big.Int).SetBytes(msgData), params, keys[i], outCh, endCh, len(msgData)).(*LocalParty) - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - var ended int32 -signing: - for { - fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break signing - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case <-endCh: - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { - t.Logf("Done. Received signature data from %d participants", ended) - R := parties[0].temp.bigR - r := parties[0].temp.rx - fmt.Printf("sign result: R(%s, %s), r=%s\n", R.X().String(), R.Y().String(), r.String()) - - modN := common.ModInt(tss.S256().Params().N) - - // BEGIN check s correctness - sumS := big.NewInt(0) - for _, p := range parties { - sumS = modN.Add(sumS, p.temp.si) - } - fmt.Printf("S: %s\n", sumS.String()) - // END check s correctness - - // BEGIN ECDSA verify - pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y() - pk := ecdsa.PublicKey{ - Curve: tss.EC(), - X: pkX, - Y: pkY, - } - ok := ecdsa.Verify(&pk, msgData, R.X(), sumS) - assert.True(t, ok, "ecdsa verify must pass") - t.Log("ECDSA signing test done.") - // END ECDSA verify - - break signing - } - } - } -} - -func TestE2EWithHDKeyDerivation(t *testing.T) { - setUp("info") - threshold := testThreshold - - // PHASE: load keygen fixtures - keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) - assert.NoError(t, err, "should load keygen fixtures") - assert.Equal(t, testThreshold+1, len(keys)) - assert.Equal(t, testThreshold+1, len(signPIDs)) - - chainCode := make([]byte, 32) - max32b := new(big.Int).Lsh(new(big.Int).SetUint64(1), 256) - max32b = new(big.Int).Sub(max32b, new(big.Int).SetUint64(1)) - fillBytes(common.GetRandomPositiveInt(rand.Reader, max32b), chainCode) - - il, extendedChildPk, errorDerivation := derivingPubkeyFromPath(keys[0].ECDSAPub, chainCode, []uint32{12, 209, 3}, btcec.S256()) - assert.NoErrorf(t, errorDerivation, "there should not be an error deriving the child public key") - - keyDerivationDelta := il - - err = UpdatePublicKeyAndAdjustBigXj(keyDerivationDelta, keys, &extendedChildPk.PublicKey, btcec.S256()) - assert.NoErrorf(t, err, "there should not be an error setting the derived keys") - - // PHASE: signing - // use a shuffled selection of the list of parties for this test - p2pCtx := tss.NewPeerContext(signPIDs) - parties := make([]*LocalParty, 0, len(signPIDs)) - - errCh := make(chan *tss.Error, len(signPIDs)) - outCh := make(chan tss.Message, len(signPIDs)) - endCh := make(chan *common.SignatureData, len(signPIDs)) - - updater := test.SharedPartyUpdater - - // init the parties - for i := 0; i < len(signPIDs); i++ { - params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - - P := NewLocalPartyWithKDD(big.NewInt(42), params, keys[i], keyDerivationDelta, outCh, endCh, 0).(*LocalParty) - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - var ended int32 -signing: - for { - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break signing - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case <-endCh: - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { - t.Logf("Done. Received signature data from %d participants", ended) - R := parties[0].temp.bigR - r := parties[0].temp.rx - fmt.Printf("sign result: R(%s, %s), r=%s\n", R.X().String(), R.Y().String(), r.String()) - - modN := common.ModInt(tss.S256().Params().N) - - // BEGIN check s correctness - sumS := big.NewInt(0) - for _, p := range parties { - sumS = modN.Add(sumS, p.temp.si) - } - fmt.Printf("S: %s\n", sumS.String()) - // END check s correctness - - // BEGIN ECDSA verify - pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y() - pk := ecdsa.PublicKey{ - Curve: tss.EC(), - X: pkX, - Y: pkY, - } - ok := ecdsa.Verify(&pk, big.NewInt(42).Bytes(), R.X(), sumS) - assert.True(t, ok, "ecdsa verify must pass") - t.Log("ECDSA signing test done.") - // END ECDSA verify - - break signing - } - } - } -} - -func TestFillTo32BytesInPlace(t *testing.T) { - s := big.NewInt(123456789) - normalizedS := padToLengthBytesInPlace(s.Bytes(), 32) - assert.True(t, big.NewInt(0).SetBytes(normalizedS).Cmp(s) == 0) - assert.Equal(t, 32, len(normalizedS)) - assert.NotEqual(t, 32, len(s.Bytes())) -} - -func fillBytes(x *big.Int, buf []byte) []byte { - b := x.Bytes() - if len(b) > len(buf) { - panic("buffer too small") - } - offset := len(buf) - len(b) - for i := range buf { - if i < offset { - buf[i] = 0 - } else { - buf[i] = b[i-offset] - } - } - return buf -} diff --git a/tss-lib/ecdsa/signing/messages.go b/tss-lib/ecdsa/signing/messages.go index b0546c6..6a617aa 100644 --- a/tss-lib/ecdsa/signing/messages.go +++ b/tss-lib/ecdsa/signing/messages.go @@ -1,391 +1,254 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package signing import ( - "crypto/elliptic" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/mta" - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -// These messages were generated from Protocol Buffers definitions into ecdsa-signing.pb.go -// The following messages are registered on the Protocol Buffers "wire" - -var ( - // Ensure that signing messages implement ValidateBasic - _ = []tss.MessageContent{ - (*SignRound1Message1)(nil), - (*SignRound1Message2)(nil), - (*SignRound2Message)(nil), - (*SignRound3Message)(nil), - (*SignRound4Message)(nil), - (*SignRound5Message)(nil), - (*SignRound6Message)(nil), - (*SignRound7Message)(nil), - (*SignRound8Message)(nil), - (*SignRound9Message)(nil), - } -) - -// ----- // - -func NewSignRound1Message1( - to, from *tss.PartyID, - c *big.Int, - proof *mta.RangeProofAlice, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - } - pfBz := proof.Bytes() - content := &SignRound1Message1{ - C: c.Bytes(), - RangeProofAlice: pfBz[:], - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// SignRound1Message1 is a P2P message: Paillier ciphertext + range proof. +type SignRound1Message1 struct { + C *big.Int + RangeProofAlice *mta.RangeProofAlice + ReceiverID []byte } +// ValidateBasic checks that required fields of SignRound1Message1 are non-nil. func (m *SignRound1Message1) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.GetC()) && - common.NonEmptyMultiBytes(m.GetRangeProofAlice(), mta.RangeProofAliceBytesParts) + return m != nil && m.C != nil && m.C.Sign() > 0 && + m.RangeProofAlice != nil && len(m.ReceiverID) > 0 } -func (m *SignRound1Message1) UnmarshalC() *big.Int { - return new(big.Int).SetBytes(m.GetC()) +// NewSignRound1Message1 constructs a *tss.Message with the given content. +func NewSignRound1Message1(to, from *tss.PartyID, c *big.Int, proof *mta.RangeProofAlice) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &SignRound1Message1{ + C: c, + RangeProofAlice: proof, + ReceiverID: to.Key, + }, + } } -func (m *SignRound1Message1) UnmarshalRangeProofAlice() (*mta.RangeProofAlice, error) { - return mta.RangeProofAliceFromBytes(m.GetRangeProofAlice()) +// SignRound1Message2 is broadcast: commitment to gamma share. +type SignRound1Message2 struct { + Commitment *big.Int } -// ----- // +// ValidateBasic checks that required fields of SignRound1Message2 are non-nil. +func (m *SignRound1Message2) ValidateBasic() bool { + return m != nil && m.Commitment != nil && m.Commitment.Sign() > 0 +} -func NewSignRound1Message2( - from *tss.PartyID, - commitment cmt.HashCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound1Message2 constructs a *tss.Message with the given content. +func NewSignRound1Message2(from *tss.PartyID, commitment cmt.HashCommitment) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound1Message2{ + Commitment: commitment, + }, } - content := &SignRound1Message2{ - Commitment: commitment.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *SignRound1Message2) ValidateBasic() bool { - return m.Commitment != nil && - common.NonEmptyBytes(m.GetCommitment()) -} - -func (m *SignRound1Message2) UnmarshalCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetCommitment()) } -// ----- // - -func NewSignRound2Message( - to, from *tss.PartyID, - c1Ji *big.Int, - pi1Ji *mta.ProofBob, - c2Ji *big.Int, - pi2Ji *mta.ProofBobWC, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - } - pfBob := pi1Ji.Bytes() - pfBobWC := pi2Ji.Bytes() - content := &SignRound2Message{ - C1: c1Ji.Bytes(), - C2: c2Ji.Bytes(), - ProofBob: pfBob[:], - ProofBobWc: pfBobWC[:], - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// SignRound2Message is P2P: MtA ciphertexts + Bob proofs. +type SignRound2Message struct { + C1 *big.Int + C2 *big.Int + ProofBob *mta.ProofBob + ProofBobWC *mta.ProofBobWC + ReceiverID []byte } +// ValidateBasic checks that required fields of SignRound2Message are non-nil. func (m *SignRound2Message) ValidateBasic() bool { return m != nil && - common.NonEmptyBytes(m.C1) && - common.NonEmptyBytes(m.C2) && - common.NonEmptyMultiBytes(m.ProofBob, mta.ProofBobBytesParts) && - common.NonEmptyMultiBytes(m.ProofBobWc, mta.ProofBobWCBytesParts) + m.C1 != nil && m.C1.Sign() > 0 && + m.C2 != nil && m.C2.Sign() > 0 && + m.ProofBob != nil && m.ProofBobWC != nil && + len(m.ReceiverID) > 0 } -func (m *SignRound2Message) UnmarshalProofBob() (*mta.ProofBob, error) { - return mta.ProofBobFromBytes(m.ProofBob) +// NewSignRound2Message constructs a *tss.Message with the given content. +func NewSignRound2Message(to, from *tss.PartyID, c1Ji *big.Int, pi1Ji *mta.ProofBob, c2Ji *big.Int, pi2Ji *mta.ProofBobWC) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &SignRound2Message{ + C1: c1Ji, + C2: c2Ji, + ProofBob: pi1Ji, + ProofBobWC: pi2Ji, + ReceiverID: to.Key, + }, + } } -func (m *SignRound2Message) UnmarshalProofBobWC(ec elliptic.Curve) (*mta.ProofBobWC, error) { - return mta.ProofBobWCFromBytes(ec, m.ProofBobWc) -} - -// ----- // - -func NewSignRound3Message( - from *tss.PartyID, - theta *big.Int, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - IsBroadcast: true, - } - content := &SignRound3Message{ - Theta: theta.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// SignRound3Message is broadcast: theta share. +type SignRound3Message struct { + Theta *big.Int } +// ValidateBasic checks that required fields of SignRound3Message are non-nil. func (m *SignRound3Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.Theta) + return m != nil && m.Theta != nil && m.Theta.Sign() > 0 } -// ----- // - -func NewSignRound4Message( - from *tss.PartyID, - deCommitment cmt.HashDeCommitment, - proof *schnorr.ZKProof, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound3Message constructs a *tss.Message with the given content. +func NewSignRound3Message(from *tss.PartyID, theta *big.Int) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound3Message{Theta: theta}, } - dcBzs := common.BigIntsToBytes(deCommitment) - content := &SignRound4Message{ - DeCommitment: dcBzs, - ProofAlphaX: proof.Alpha.X().Bytes(), - ProofAlphaY: proof.Alpha.Y().Bytes(), - ProofT: proof.T.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *SignRound4Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.DeCommitment, 3) && - common.NonEmptyBytes(m.ProofAlphaX) && - common.NonEmptyBytes(m.ProofAlphaY) && - common.NonEmptyBytes(m.ProofT) } -func (m *SignRound4Message) UnmarshalDeCommitment() []*big.Int { - deComBzs := m.GetDeCommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) +// SignRound4Message is broadcast: decommitment to gamma + ZK proof. +type SignRound4Message struct { + DeCommitment cmt.HashDeCommitment + ZKProof *schnorr.ZKProof } -func (m *SignRound4Message) UnmarshalZKProof(ec elliptic.Curve) (*schnorr.ZKProof, error) { - point, err := crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.GetProofAlphaX()), - new(big.Int).SetBytes(m.GetProofAlphaY())) - if err != nil { - return nil, err - } - return &schnorr.ZKProof{ - Alpha: point, - T: new(big.Int).SetBytes(m.GetProofT()), - }, nil +// ValidateBasic checks that required fields of SignRound4Message are non-nil. +func (m *SignRound4Message) ValidateBasic() bool { + return m != nil && len(m.DeCommitment) >= 2 && m.ZKProof != nil } -// ----- // - -func NewSignRound5Message( - from *tss.PartyID, - commitment cmt.HashCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound4Message constructs a *tss.Message with the given content. +func NewSignRound4Message(from *tss.PartyID, deCommitment cmt.HashDeCommitment, proof *schnorr.ZKProof) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound4Message{ + DeCommitment: deCommitment, + ZKProof: proof, + }, } - content := &SignRound5Message{ - Commitment: commitment.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *SignRound5Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.Commitment) +// SignRound5Message is broadcast: commitment to blinding. +type SignRound5Message struct { + Commitment *big.Int } -func (m *SignRound5Message) UnmarshalCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetCommitment()) +// ValidateBasic checks that required fields of SignRound5Message are non-nil. +func (m *SignRound5Message) ValidateBasic() bool { + return m != nil && m.Commitment != nil && m.Commitment.Sign() > 0 } -// ----- // - -func NewSignRound6Message( - from *tss.PartyID, - deCommitment cmt.HashDeCommitment, - proof *schnorr.ZKProof, - vProof *schnorr.ZKVProof, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound5Message constructs a *tss.Message with the given content. +func NewSignRound5Message(from *tss.PartyID, commitment cmt.HashCommitment) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound5Message{ + Commitment: commitment, + }, } - dcBzs := common.BigIntsToBytes(deCommitment) - content := &SignRound6Message{ - DeCommitment: dcBzs, - ProofAlphaX: proof.Alpha.X().Bytes(), - ProofAlphaY: proof.Alpha.Y().Bytes(), - ProofT: proof.T.Bytes(), - VProofAlphaX: vProof.Alpha.X().Bytes(), - VProofAlphaY: vProof.Alpha.Y().Bytes(), - VProofT: vProof.T.Bytes(), - VProofU: vProof.U.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *SignRound6Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.DeCommitment, 5) && - common.NonEmptyBytes(m.ProofAlphaX) && - common.NonEmptyBytes(m.ProofAlphaY) && - common.NonEmptyBytes(m.ProofT) && - common.NonEmptyBytes(m.VProofAlphaX) && - common.NonEmptyBytes(m.VProofAlphaY) && - common.NonEmptyBytes(m.VProofT) && - common.NonEmptyBytes(m.VProofU) +// SignRound6Message is broadcast: decommitment + ZK + ZKV proofs. +type SignRound6Message struct { + DeCommitment cmt.HashDeCommitment + ZKProof *schnorr.ZKProof + ZKVProof *schnorr.ZKVProof } -func (m *SignRound6Message) UnmarshalDeCommitment() []*big.Int { - deComBzs := m.GetDeCommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) +// ValidateBasic checks that required fields of SignRound6Message are non-nil. +func (m *SignRound6Message) ValidateBasic() bool { + return m != nil && len(m.DeCommitment) >= 2 && + m.ZKProof != nil && m.ZKVProof != nil } -func (m *SignRound6Message) UnmarshalZKProof(ec elliptic.Curve) (*schnorr.ZKProof, error) { - point, err := crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.GetProofAlphaX()), - new(big.Int).SetBytes(m.GetProofAlphaY())) - if err != nil { - return nil, err +// NewSignRound6Message constructs a *tss.Message with the given content. +func NewSignRound6Message(from *tss.PartyID, deCommitment cmt.HashDeCommitment, proof *schnorr.ZKProof, vProof *schnorr.ZKVProof) *tss.Message { + return &tss.Message{ + From: from, + IsBroadcast: true, + Content: &SignRound6Message{ + DeCommitment: deCommitment, + ZKProof: proof, + ZKVProof: vProof, + }, } - return &schnorr.ZKProof{ - Alpha: point, - T: new(big.Int).SetBytes(m.GetProofT()), - }, nil } -func (m *SignRound6Message) UnmarshalZKVProof(ec elliptic.Curve) (*schnorr.ZKVProof, error) { - point, err := crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.GetVProofAlphaX()), - new(big.Int).SetBytes(m.GetVProofAlphaY())) - if err != nil { - return nil, err - } - return &schnorr.ZKVProof{ - Alpha: point, - T: new(big.Int).SetBytes(m.GetVProofT()), - U: new(big.Int).SetBytes(m.GetVProofU()), - }, nil +// SignRound7Message is broadcast: commitment to Ui/Ti. +type SignRound7Message struct { + Commitment *big.Int } -// ----- // +// ValidateBasic checks that required fields of SignRound7Message are non-nil. +func (m *SignRound7Message) ValidateBasic() bool { + return m != nil && m.Commitment != nil && m.Commitment.Sign() > 0 +} -func NewSignRound7Message( - from *tss.PartyID, - commitment cmt.HashCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound7Message constructs a *tss.Message with the given content. +func NewSignRound7Message(from *tss.PartyID, commitment cmt.HashCommitment) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound7Message{ + Commitment: commitment, + }, } - content := &SignRound7Message{ - Commitment: commitment.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *SignRound7Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.Commitment) +// SignRound8Message is broadcast: decommitment of Ui/Ti. +type SignRound8Message struct { + DeCommitment cmt.HashDeCommitment } -func (m *SignRound7Message) UnmarshalCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetCommitment()) +// ValidateBasic checks that required fields of SignRound8Message are non-nil. +func (m *SignRound8Message) ValidateBasic() bool { + return m != nil && len(m.DeCommitment) >= 2 } -// ----- // - -func NewSignRound8Message( - from *tss.PartyID, - deCommitment cmt.HashDeCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound8Message constructs a *tss.Message with the given content. +func NewSignRound8Message(from *tss.PartyID, deCommitment cmt.HashDeCommitment) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound8Message{ + DeCommitment: deCommitment, + }, } - dcBzs := common.BigIntsToBytes(deCommitment) - content := &SignRound8Message{ - DeCommitment: dcBzs, - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *SignRound8Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.DeCommitment, 5) +// SignRound9Message is broadcast: partial signature share. +type SignRound9Message struct { + S *big.Int } -func (m *SignRound8Message) UnmarshalDeCommitment() []*big.Int { - deComBzs := m.GetDeCommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) +// ValidateBasic checks that required fields of SignRound9Message are non-nil. +func (m *SignRound9Message) ValidateBasic() bool { + return m != nil && m.S != nil && m.S.Sign() > 0 } -// ----- // - -func NewSignRound9Message( - from *tss.PartyID, - si *big.Int, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound9Message constructs a *tss.Message with the given content. +func NewSignRound9Message(from *tss.PartyID, si *big.Int) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound9Message{S: si}, } - content := &SignRound9Message{ - S: si.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *SignRound9Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.S) } -func (m *SignRound9Message) UnmarshalS() *big.Int { - return new(big.Int).SetBytes(m.S) +// SignatureData holds the final ECDSA signature components. +type SignatureData struct { + R []byte + S []byte + Signature []byte // DER-encoded signature (optional) + SignatureRecovery []byte + M []byte // message hash } diff --git a/tss-lib/ecdsa/signing/messages_test.go b/tss-lib/ecdsa/signing/messages_test.go new file mode 100644 index 0000000..158dd3c --- /dev/null +++ b/tss-lib/ecdsa/signing/messages_test.go @@ -0,0 +1,89 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + "testing" + + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" +) + +func TestValidateBasicAllSignMessages(t *testing.T) { + pt := &schnorr.ZKProof{Alpha: nil} + vpt := &schnorr.ZKVProof{Alpha: nil} + + tests := []struct { + name string + valid interface{ ValidateBasic() bool } + bad interface{ ValidateBasic() bool } + }{ + { + "SignRound1Message1", + &SignRound1Message1{C: big.NewInt(1), RangeProofAlice: &mta.RangeProofAlice{}, ReceiverID: []byte("r")}, + &SignRound1Message1{}, + }, + { + "SignRound1Message2", + &SignRound1Message2{Commitment: big.NewInt(1)}, + &SignRound1Message2{}, + }, + { + "SignRound2Message", + &SignRound2Message{C1: big.NewInt(1), C2: big.NewInt(2), ProofBob: &mta.ProofBob{}, ProofBobWC: &mta.ProofBobWC{}, ReceiverID: []byte("r")}, + &SignRound2Message{}, + }, + { + "SignRound3Message", + &SignRound3Message{Theta: big.NewInt(1)}, + &SignRound3Message{}, + }, + { + "SignRound4Message", + &SignRound4Message{DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, ZKProof: pt}, + &SignRound4Message{}, + }, + { + "SignRound5Message", + &SignRound5Message{Commitment: big.NewInt(1)}, + &SignRound5Message{}, + }, + { + "SignRound6Message", + &SignRound6Message{DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, ZKProof: pt, ZKVProof: vpt}, + &SignRound6Message{}, + }, + { + "SignRound7Message", + &SignRound7Message{Commitment: big.NewInt(1)}, + &SignRound7Message{}, + }, + { + "SignRound8Message", + &SignRound8Message{DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}}, + &SignRound8Message{}, + }, + { + "SignRound9Message", + &SignRound9Message{S: big.NewInt(1)}, + &SignRound9Message{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name+"_valid", func(t *testing.T) { + if !tt.valid.ValidateBasic() { + t.Fatal("valid message should pass") + } + }) + t.Run(tt.name+"_invalid", func(t *testing.T) { + if tt.bad.ValidateBasic() { + t.Fatal("empty message should fail") + } + }) + } +} diff --git a/tss-lib/ecdsa/signing/prepare.go b/tss-lib/ecdsa/signing/prepare.go index c03da97..1020ff5 100644 --- a/tss-lib/ecdsa/signing/prepare.go +++ b/tss-lib/ecdsa/signing/prepare.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package signing @@ -11,13 +10,15 @@ import ( "fmt" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" ) // PrepareForSigning(), GG18Spec (11) Fig. 14 func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int, bigXs []*crypto.ECPoint) (wi *big.Int, bigWs []*crypto.ECPoint) { modQ := common.ModInt(ec.Params().N) + // Precondition panics (same as upstream). The [FORK] changes in this file are the + // Set() copy on line 36 and the nil-checks on ModInverse below. if len(ks) != len(bigXs) { panic(fmt.Errorf("PrepareForSigning: len(ks) != len(bigXs) (%d != %d)", len(ks), len(bigXs))) } @@ -29,7 +30,9 @@ func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int } // 2-4. - wi = xi + // [FORK] Upstream: `wi = xi` aliases the pointer, so subsequent Mul() calls + // mutate the caller's xi in-place, corrupting the key share. Use Set() to copy. + wi = new(big.Int).Set(xi) // explicit copy to avoid mutating key material for j := 0; j < pax; j++ { if j == i { continue @@ -40,10 +43,38 @@ func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int panic(fmt.Errorf("index of two parties are equal")) } // big.Int Div is calculated as: a/b = a * modInv(b,q) - coef := modQ.Mul(ks[j], modQ.ModInverse(new(big.Int).Sub(ksj, ksi))) + diff := new(big.Int).Sub(ksj, ksi) + inv := modQ.ModInverse(diff) + // [FORK] Nil-check on ModInverse: upstream does not check. If two party keys + // collide mod q, ModInverse returns nil, causing a nil-pointer panic in Mul(). + if inv == nil { + panic(fmt.Errorf("PrepareForSigning: ModInverse(ks[%d]-ks[%d]) is nil; keys may collide mod q", j, i)) + } + coef := modQ.Mul(ks[j], inv) wi = modQ.Mul(wi, coef) } + // [FORK] Defense-in-depth: wi == 0 means this party's secret share contribution + // is annihilated, which would silently corrupt the threshold signature (zero + // signature share propagates through MtA, producing k*w = 0 regardless of nonce). + // + // This condition is unreachable under normal operation for the following reasons: + // 1. xi != 0 is validated at keygen (round_3.go:48-50) and resharing + // (round_4_new_step_2.go:257-259), and VSS Share.Verify() rejects zero shares. + // 2. ks[j] != 0 mod q is validated by vss.CheckIndexes() during keygen/reshare, + // which checks v mod q != 0 for all party indices. + // 3. Since q is prime, Z/qZ is a field where the product of non-zero elements + // is always non-zero. Therefore wi = xi * ∏(ks[j] / (ks[j] - ks[i])) cannot + // be zero when all factors are non-zero. + // + // The only theoretical (negligible-probability) path is via BIP-32 key derivation: + // if keyDerivationDelta == -xi mod q (probability 1/q ≈ 2^{-256}), the derived xi + // becomes zero. This check catches that edge case as well as any data corruption + // of xi or ks values loaded from storage. + if wi.Sign() == 0 { + panic(fmt.Errorf("PrepareForSigning: wi is zero after Lagrange interpolation for party %d; xi or party keys may be degenerate", i)) + } + // 5-10. bigWs = make([]*crypto.ECPoint, len(ks)) for j := 0; j < pax; j++ { @@ -58,8 +89,14 @@ func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int panic(fmt.Errorf("index of two parties are equal")) } // big.Int Div is calculated as: a/b = a * modInv(b,q) - iota := modQ.Mul(ksc, modQ.ModInverse(new(big.Int).Sub(ksc, ksj))) - bigWj = bigWj.ScalarMult(iota) + diff := new(big.Int).Sub(ksc, ksj) + inv := modQ.ModInverse(diff) + // [FORK] Same nil-check as above for the BigXj Lagrange interpolation loop. + if inv == nil { + panic(fmt.Errorf("PrepareForSigning: ModInverse(ks[%d]-ks[%d]) is nil; keys may collide mod q", c, j)) + } + iotaVal := modQ.Mul(ksc, inv) + bigWj = bigWj.ScalarMult(iotaVal) } bigWs[j] = bigWj } diff --git a/tss-lib/ecdsa/signing/prepare_test.go b/tss-lib/ecdsa/signing/prepare_test.go new file mode 100644 index 0000000..678929b --- /dev/null +++ b/tss-lib/ecdsa/signing/prepare_test.go @@ -0,0 +1,60 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestPrepareForSigningNoXiMutation(t *testing.T) { + // Setup: 3 parties, threshold=1 + ec := tss.S256() + q := ec.Params().N + + // Create distinct party keys + ks := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + xi := new(big.Int).SetInt64(42) // Some secret share + xiCopy := new(big.Int).Set(xi) // Save original value + + // Create dummy public keys (just generator multiples) + bigXs := make([]*crypto.ECPoint, 3) + for j := 0; j < 3; j++ { + bigXs[j] = crypto.ScalarBaseMult(ec, big.NewInt(int64(j+10))) + } + + // Call PrepareForSigning for party 0 + _, _ = PrepareForSigning(ec, 0, 3, xi, ks, bigXs) + + // xi should NOT have been mutated + if xi.Cmp(xiCopy) != 0 { + t.Fatalf("xi must not be mutated by PrepareForSigning") + } + _ = q // suppress unused warning if needed +} + +func TestPrepareForSigningCollidingKeysPanics(t *testing.T) { + ec := tss.S256() + + ks := []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(3)} // ks[0] == ks[1] + xi := big.NewInt(42) + + bigXs := make([]*crypto.ECPoint, 3) + for j := 0; j < 3; j++ { + bigXs[j] = crypto.ScalarBaseMult(ec, big.NewInt(int64(j+10))) + } + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("colliding keys should panic") + } + }() + PrepareForSigning(ec, 0, 3, xi, ks, bigXs) + }() +} diff --git a/tss-lib/ecdsa/signing/round1_round2_negative_test.go b/tss-lib/ecdsa/signing/round1_round2_negative_test.go new file mode 100644 index 0000000..c228088 --- /dev/null +++ b/tss-lib/ecdsa/signing/round1_round2_negative_test.go @@ -0,0 +1,176 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// --------------------------------------------------------------------------- +// SignRound1 negative tests +// --------------------------------------------------------------------------- + +// TestSignRound1RejectsNegativeMessage verifies that SignRound1 rejects a +// message hash with a negative value (msg.Sign() < 0). +// Exercises the guard at round_fn.go:99. +func TestSignRound1RejectsNegativeMessage(t *testing.T) { + keys := doKeygen(t) + pIDs, peerCtx := setupPartyIDs() + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], testN, testThreshold) + + negMsg := big.NewInt(-1) + _, _, err := SignRound1(params, keys[0], negMsg, nil, 0) + if err == nil { + t.Fatal("expected error for negative message, got nil") + } + if !strings.Contains(err.Error(), "hashed message is not valid") { + t.Fatalf("unexpected error: %v", err) + } + t.Logf("correctly rejected negative message: %v", err) +} + +// TestSignRound1RejectsMessageEqualToN verifies that SignRound1 rejects a +// message hash equal to the curve order N (must be strictly < N). +// Also tests msg = N+1 for completeness. +// Exercises the guard at round_fn.go:99. +func TestSignRound1RejectsMessageEqualToN(t *testing.T) { + keys := doKeygen(t) + pIDs, peerCtx := setupPartyIDs() + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], testN, testThreshold) + curveOrder := tss.S256().Params().N + + // msg == N + msgN := new(big.Int).Set(curveOrder) + _, _, err := SignRound1(params, keys[0], msgN, nil, 0) + if err == nil { + t.Fatal("expected error for msg == N, got nil") + } + if !strings.Contains(err.Error(), "hashed message is not valid") { + t.Fatalf("unexpected error for msg == N: %v", err) + } + t.Logf("correctly rejected msg == N: %v", err) + + // msg == N+1 + msgN1 := new(big.Int).Add(curveOrder, big.NewInt(1)) + _, _, err = SignRound1(params, keys[0], msgN1, nil, 0) + if err == nil { + t.Fatal("expected error for msg == N+1, got nil") + } + if !strings.Contains(err.Error(), "hashed message is not valid") { + t.Fatalf("unexpected error for msg == N+1: %v", err) + } + t.Logf("correctly rejected msg == N+1: %v", err) +} + +// TestSignRound1RejectsKeyCountMismatch verifies that SignRound1 rejects +// when key.Ks has fewer entries than params.PartyCount(). +// Exercises the guard at round_fn.go:110-111. +func TestSignRound1RejectsKeyCountMismatch(t *testing.T) { + keys := doKeygen(t) + pIDs, peerCtx := setupPartyIDs() + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[0], testN, testThreshold) + m := testMsg() + + // Truncate key data so len(Ks) = 2 but params.PartyCount() = 3. + // Since 2 < 3, the auto-subset branch is skipped and the + // "key count != party count" check triggers. + truncated := keys[0] + truncated.Ks = truncated.Ks[:2] + truncated.BigXj = truncated.BigXj[:2] + truncated.NTildej = truncated.NTildej[:2] + truncated.H1j = truncated.H1j[:2] + truncated.H2j = truncated.H2j[:2] + truncated.PaillierPKs = truncated.PaillierPKs[:2] + + _, _, err := SignRound1(params, truncated, m, nil, 0) + if err == nil { + t.Fatal("expected error for key count mismatch, got nil") + } + if !strings.Contains(err.Error(), "key count") || !strings.Contains(err.Error(), "party count") { + t.Fatalf("unexpected error: %v", err) + } + t.Logf("correctly rejected key count mismatch: %v", err) +} + +// --------------------------------------------------------------------------- +// SignRound2 negative tests +// --------------------------------------------------------------------------- + +// TestSignRound2RejectsReceiverIDMismatch verifies that SignRound2 rejects +// a P2P message whose ReceiverID does not match the receiving party's key. +// Exercises the guard at round_fn.go:189-191. +func TestSignRound2RejectsReceiverIDMismatch(t *testing.T) { + keys := doKeygen(t) + f := setupSignRound1(t, keys) + + // Deep-clone the P2P messages destined for party 0 so we can corrupt one. + corruptP2P := CloneP2PSlice(f.R1P2P, CloneR1P2PMsg) + + // Corrupt ReceiverID in the message from sender=1 to recipient=0. + corruptContent := corruptP2P[0][1].Content.(*SignRound1Message1) + corruptContent.ReceiverID = []byte("wrong-receiver-id") + + _, err := SignRound2(context.Background(), f.States[0], corruptP2P[0], f.R1Bcast) + if err == nil { + t.Fatal("expected error for receiverId mismatch, got nil") + } + if !strings.Contains(err.Error(), "receiverId mismatch") { + t.Fatalf("unexpected error: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("correctly rejected receiverId mismatch: %v", err) +} + +// TestSignRound2RejectsNilRangeProofAlice verifies that SignRound2 rejects +// a P2P message where RangeProofAlice is nil. +// Exercises the guard at round_fn.go:212-216 and :243-247 (both goroutines). +func TestSignRound2RejectsNilRangeProofAlice(t *testing.T) { + keys := doKeygen(t) + f := setupSignRound1(t, keys) + + // Deep-clone the P2P messages destined for party 0 so we can corrupt one. + corruptP2P := CloneP2PSlice(f.R1P2P, CloneR1P2PMsg) + + // Set RangeProofAlice to nil in the message from sender=1 to recipient=0. + corruptContent := corruptP2P[0][1].Content.(*SignRound1Message1) + corruptContent.RangeProofAlice = nil + + _, err := SignRound2(context.Background(), f.States[0], corruptP2P[0], f.R1Bcast) + if err == nil { + t.Fatal("expected error for nil RangeProofAlice, got nil") + } + if !strings.Contains(err.Error(), "RangeProofAlice missing") { + t.Fatalf("unexpected error: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("correctly rejected nil RangeProofAlice: %v", err) +} + +// TestSignRound2ContextCancellation verifies that SignRound2 returns an +// error when the context is already cancelled before the MtA goroutines run. +// Exercises the guard at round_fn.go:269-271. +func TestSignRound2ContextCancellation(t *testing.T) { + keys := doKeygen(t) + f := setupSignRound1(t, keys) + + // Create an already-cancelled context. + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + _, err := SignRound2(ctx, f.States[0], f.R1P2P[0], f.R1Bcast) + if err == nil { + t.Fatal("expected error for cancelled context, got nil") + } + // The error should be context.Canceled, either directly or wrapped. + if !strings.Contains(err.Error(), "context canceled") { + t.Fatalf("unexpected error: %v", err) + } + t.Logf("correctly rejected cancelled context: %v", err) +} diff --git a/tss-lib/ecdsa/signing/round3_negative_test.go b/tss-lib/ecdsa/signing/round3_negative_test.go new file mode 100644 index 0000000..0a64edf --- /dev/null +++ b/tss-lib/ecdsa/signing/round3_negative_test.go @@ -0,0 +1,112 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "context" + "strings" + "testing" +) + +// TestSignRound3RejectsReceiverIDMismatch verifies that SignRound3 returns an +// error when a Round 2 P2P message has a ReceiverID that does not match the +// processing party's key. +func TestSignRound3RejectsReceiverIDMismatch(t *testing.T) { + f := setupThroughRound2(t) + + victim := 0 + corrupted := CloneBcastSlice(f.R2P2P[victim], CloneR2P2PMsg) + + // Corrupt the ReceiverID in the first non-nil message from another party. + for j := 0; j < testN; j++ { + if j == victim || corrupted[j] == nil { + continue + } + corrupted[j].Content.(*SignRound2Message).ReceiverID = []byte("wrong-receiver-id") + break + } + + _, err := SignRound3(context.Background(), f.States[victim], corrupted) + if err == nil { + t.Fatal("expected error for ReceiverID mismatch, got nil") + } + if !strings.Contains(err.Error(), "receiverId mismatch") { + t.Fatalf("expected 'receiverId mismatch' in error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("correctly rejected ReceiverID mismatch: %v", err) +} + +// TestSignRound3RejectsNilProofBob verifies that SignRound3 returns an error +// when a Round 2 P2P message has a nil ProofBob field. +func TestSignRound3RejectsNilProofBob(t *testing.T) { + f := setupThroughRound2(t) + + victim := 0 + corrupted := CloneBcastSlice(f.R2P2P[victim], CloneR2P2PMsg) + + for j := 0; j < testN; j++ { + if j == victim || corrupted[j] == nil { + continue + } + corrupted[j].Content.(*SignRound2Message).ProofBob = nil + break + } + + _, err := SignRound3(context.Background(), f.States[victim], corrupted) + if err == nil { + t.Fatal("expected error for nil ProofBob, got nil") + } + if !strings.Contains(err.Error(), "ProofBob missing") { + t.Fatalf("expected 'ProofBob missing' in error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("correctly rejected nil ProofBob: %v", err) +} + +// TestSignRound3RejectsNilProofBobWC verifies that SignRound3 returns an error +// when a Round 2 P2P message has a nil ProofBobWC field. +func TestSignRound3RejectsNilProofBobWC(t *testing.T) { + f := setupThroughRound2(t) + + victim := 0 + corrupted := CloneBcastSlice(f.R2P2P[victim], CloneR2P2PMsg) + + for j := 0; j < testN; j++ { + if j == victim || corrupted[j] == nil { + continue + } + corrupted[j].Content.(*SignRound2Message).ProofBobWC = nil + break + } + + _, err := SignRound3(context.Background(), f.States[victim], corrupted) + if err == nil { + t.Fatal("expected error for nil ProofBobWC, got nil") + } + if !strings.Contains(err.Error(), "ProofBobWC missing") { + t.Fatalf("expected 'ProofBobWC missing' in error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("correctly rejected nil ProofBobWC: %v", err) +} + +// TestSignRound3ContextCancellation verifies that SignRound3 returns an error +// when the context is already cancelled before invocation. +func TestSignRound3ContextCancellation(t *testing.T) { + f := setupThroughRound2(t) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() // cancel immediately + + _, err := SignRound3(ctx, f.States[0], f.R2P2P[0]) + if err == nil { + t.Fatal("expected error for cancelled context, got nil") + } + if !strings.Contains(err.Error(), "context canceled") { + t.Fatalf("expected 'context canceled' in error, got: %v", err) + } + t.Logf("correctly rejected cancelled context: %v", err) +} diff --git a/tss-lib/ecdsa/signing/round4_round5_negative_test.go b/tss-lib/ecdsa/signing/round4_round5_negative_test.go new file mode 100644 index 0000000..ceabe64 --- /dev/null +++ b/tss-lib/ecdsa/signing/round4_round5_negative_test.go @@ -0,0 +1,196 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +// Negative tests for SignRound4 and SignRound5. +// +// SignRound4 (round_fn.go:402-433) has 2 error paths: +// +// 1. Line 419-420: "theta is zero" — aggregate theta is zero mod N, +// so ModInverse returns nil. +// TESTABLE: corrupt Round3 theta shares to sum to zero. +// +// 2. Line 425-426: NewZKProof fails — requires gamma or pointGamma to +// be nil/invalid. +// INFEASIBLE: gamma is always a random positive int and pointGamma +// = gamma*G is always a valid curve point from honest execution. +// +// SignRound5 (round_fn.go:436-523) has 10 error paths: +// +// 1. Line 452-453: "commitment verify failed" — decommitment check fails. +// TESTABLE: corrupt the commitment in Round1Message2. +// +// 2. Line 455-457: NewECPoint fails — decommitted values not on curve. +// TESTABLE: replace commitment + decommitment with off-curve coords. +// +// 3. Line 460-461: "bigGamma proof missing" — ZKProof is nil. +// TESTABLE: set ZKProof to nil in Round4 message. +// +// 4. Line 463-464: "bigGamma proof verify failed" — ZK proof does not verify. +// TESTABLE: corrupt the ZKProof.T scalar. +// +// 5. Line 467-469: R.Add error. +// INFEASIBLE via message corruption: the point just passed NewECPoint. +// +// 6. Line 473-474: "sum of gamma points is identity". +// INFEASIBLE: gamma_i are random non-zero scalars. +// +// 7. Line 477-478: "r is identity after theta-inverse". +// INFEASIBLE: R is non-identity and thetaInverse is non-zero. +// +// 8. Line 484-485: "r component is zero" — R.X mod N == 0. +// INFEASIBLE: probability ~2^-256. +// +// 9. Line 489-490: "si is zero". +// INFEASIBLE: requires m*k + rx*sigma = 0 mod N with random k, sigma. +// +// 10. Line 505-506: "round 5 compute bigVi" — R*si + li*G Add fails. +// INFEASIBLE: both points are valid curve points. + +import ( + "math/big" + "strings" + "testing" + + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// =========================================================================== +// SignRound4 negative tests +// =========================================================================== + +func TestSignRound4RejectsZeroTheta(t *testing.T) { + f := setupThroughRound3(t) + + // Strategy: corrupt Round3 messages so that the sum of all thetas + // (party 0's own theta + party 1's theta + party 2's theta) equals + // zero mod N. + // + // Party 0's theta is stored in f.States[0].temp.theta. + // Round3 broadcasts from parties 1 and 2 each carry a Theta field. + // Set theta_1 = -theta_0 mod N, theta_2 = N (which is 0 mod N). + // Then: theta_0 + (-theta_0) + 0 = 0 mod N. + N := tss.S256().Params().N + theta0 := f.States[0].temp.theta + + r3 := CloneBcastSlice(f.R3Bcast, CloneR3BcastMsg) + + // party 1's theta = N - theta_0 (i.e., -theta_0 mod N) + negTheta0 := new(big.Int).Sub(N, theta0) + negTheta0.Mod(negTheta0, N) + r3[1].Content.(*SignRound3Message).Theta = negTheta0 + + // party 2's theta = N (which is 0 mod N, but non-zero as a big.Int + // so the type assertion won't panic). + r3[2].Content.(*SignRound3Message).Theta = new(big.Int).Set(N) + + _, err := SignRound4(f.States[0], r3) + if err == nil { + t.Fatal("expected 'theta is zero' error, but SignRound4 succeeded") + } + if !strings.Contains(err.Error(), "theta is zero") { + t.Fatalf("expected error containing 'theta is zero', got: %v", err) + } +} + +// =========================================================================== +// SignRound5 negative tests +// =========================================================================== + +func TestSignRound5RejectsBadCommitment(t *testing.T) { + f := setupThroughRound4(t) + + // Corrupt the commitment that party 1 broadcast in Round1Message2. + // SignRound5 reads this from f.States[0].temp.signRound1Message2s[1]. + r1m2 := f.States[0].temp.signRound1Message2s[1].Content.(*SignRound1Message2) + r1m2.Commitment = new(big.Int).Add(r1m2.Commitment, big.NewInt(1)) + + r4 := CloneBcastSlice(f.R4Bcast, CloneR4BcastMsg) + _, err := SignRound5(f.States[0], r4) + if err == nil { + t.Fatal("expected 'commitment verify failed' error, but SignRound5 succeeded") + } + if !strings.Contains(err.Error(), "commitment verify failed") { + t.Fatalf("expected error containing 'commitment verify failed', got: %v", err) + } + requireCulprit(t, err, 1) +} + +func TestSignRound5RejectsNilZKProof(t *testing.T) { + f := setupThroughRound4(t) + + r4 := CloneBcastSlice(f.R4Bcast, CloneR4BcastMsg) + + // Set party 1's ZKProof to nil. + r4[1].Content.(*SignRound4Message).ZKProof = nil + + _, err := SignRound5(f.States[0], r4) + if err == nil { + t.Fatal("expected 'bigGamma proof missing' error, but SignRound5 succeeded") + } + if !strings.Contains(err.Error(), "bigGamma proof missing") { + t.Fatalf("expected error containing 'bigGamma proof missing', got: %v", err) + } + requireCulprit(t, err, 1) +} + +func TestSignRound5RejectsBadZKProof(t *testing.T) { + f := setupThroughRound4(t) + + r4 := CloneBcastSlice(f.R4Bcast, CloneR4BcastMsg) + + // Corrupt the T field of party 1's ZKProof so that verification fails. + proof := r4[1].Content.(*SignRound4Message).ZKProof + proof.T = new(big.Int).Add(proof.T, big.NewInt(1)) + + _, err := SignRound5(f.States[0], r4) + if err == nil { + t.Fatal("expected 'bigGamma proof verify failed' error, but SignRound5 succeeded") + } + if !strings.Contains(err.Error(), "bigGamma proof verify failed") { + t.Fatalf("expected error containing 'bigGamma proof verify failed', got: %v", err) + } + requireCulprit(t, err, 1) +} + +func TestSignRound5RejectsBadDecommitmentPoint(t *testing.T) { + // Tests error path at line 455-457: the decommitted values form + // coordinates that are not on the curve, so NewECPoint fails. + f := setupThroughRound4(t) + + r4 := CloneBcastSlice(f.R4Bcast, CloneR4BcastMsg) + + // Strategy: replace party 1's Round1Message2 commitment AND + // Round4 decommitment with a fresh commitment to an off-curve point. + // (1, 1) is not on secp256k1 (y^2 != x^3 + 7 mod p). + offX := big.NewInt(1) + offY := big.NewInt(1) + fakeCmt := cmt.NewHashCommitment(f.States[0].params.Rand(), offX, offY) + + // Overwrite party 1's Round1Message2 commitment in party 0's state. + f.States[0].temp.signRound1Message2s[1] = &tss.Message{ + From: f.States[0].temp.signRound1Message2s[1].From, + IsBroadcast: true, + Content: &SignRound1Message2{Commitment: fakeCmt.C}, + } + + // Overwrite party 1's Round4 decommitment. The ZKProof is kept as-is + // because NewECPoint fails before the proof is checked. + r4Content := r4[1].Content.(*SignRound4Message) + r4Content.DeCommitment = fakeCmt.D + + _, err := SignRound5(f.States[0], r4) + if err == nil { + t.Fatal("expected error for off-curve decommitment point, but SignRound5 succeeded") + } + // The error comes from NewECPoint ("not on the elliptic curve") + // wrapped by tss.NewError. + if !strings.Contains(err.Error(), "not on the") { + t.Fatalf("expected 'not on the elliptic curve' error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("got expected error for off-curve point: %v", err) +} diff --git a/tss-lib/ecdsa/signing/round7_round9_negative_test.go b/tss-lib/ecdsa/signing/round7_round9_negative_test.go new file mode 100644 index 0000000..24c80c4 --- /dev/null +++ b/tss-lib/ecdsa/signing/round7_round9_negative_test.go @@ -0,0 +1,160 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Negative tests for SignRound7 and SignRound9. +// +// Error paths in SignRound7 (round_fn.go lines 546-626): +// Path 1 (tested): de-commitment failed (line 564-566) +// Path 2 (infeasible): bigVj not on curve -- commitment binding prevents +// Path 3 (infeasible): bigVj is identity -- statistically negligible +// Path 4 (infeasible): bigAj not on curve -- commitment binding prevents +// Path 5 (infeasible): bigAj is identity -- statistically negligible +// Path 6 (tested): schnorr Aj verify failed (line 583-586) +// Path 7 (tested): vverify Vj failed (line 587-590) +// Path 8 (infeasible): Ui computation fails -- ScalarMult of valid point +// Path 9 (infeasible): Ti computation fails -- ScalarMult of valid point +// +// Error paths in SignRound9 (round_fn.go lines 638-682): +// Path 1 (tested): Uj/Tj decommit failed (line 654-656) +// Path 2 (infeasible): Uj not on curve -- commitment binding +// Path 3 (infeasible): Uj is identity -- statistically negligible +// Path 4 (infeasible): Tj not on curve -- commitment binding +// Path 5 (infeasible): Tj is identity -- statistically negligible +// Path 6 (not trivially testable): U != T requires internal state manipulation + +package signing + +import ( + "math/big" + "strings" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// --------------------------------------------------------------------------- +// SignRound7 negative tests +// --------------------------------------------------------------------------- + +// TestSignRound7RejectsBadDecommitment corrupts the decommitment in a Round6 +// message so that the commit/decommit check fails (error path line 564-566). +func TestSignRound7RejectsBadDecommitment(t *testing.T) { + f := setupThroughRound6(t) + + corruptR6 := CloneBcastSlice(f.R6Bcast, CloneR6BcastMsg) + + // Flip a bit in the randomness element of party 1's decommitment. + origContent := corruptR6[1].Content.(*SignRound6Message) + corruptD := make([]*big.Int, len(origContent.DeCommitment)) + for i, v := range origContent.DeCommitment { + corruptD[i] = new(big.Int).Set(v) + } + corruptD[0].Xor(corruptD[0], big.NewInt(1)) // flip low bit + origContent.DeCommitment = corruptD + + _, err := SignRound7(f.States[0], f.R5Bcast, corruptR6) + if err == nil { + t.Fatal("expected SignRound7 to fail with corrupted decommitment, but got nil error") + } + if !strings.Contains(err.Error(), "de-commitment failed") { + t.Fatalf("expected 'de-commitment failed' error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("SignRound7 correctly rejected bad decommitment: %v", err) +} + +// TestSignRound7RejectsBadSchnorrProof corrupts the Schnorr proof T scalar +// in a Round6 message so that the Aj verification fails (line 583-586). +func TestSignRound7RejectsBadSchnorrProof(t *testing.T) { + f := setupThroughRound6(t) + + corruptR6 := CloneBcastSlice(f.R6Bcast, CloneR6BcastMsg) + + // Add 1 to the Schnorr proof T scalar for party 1. + origContent := corruptR6[1].Content.(*SignRound6Message) + N := tss.S256().Params().N + corruptT := new(big.Int).Add(origContent.ZKProof.T, big.NewInt(1)) + corruptT.Mod(corruptT, N) + if corruptT.Sign() == 0 { + corruptT.SetInt64(1) + } + origContent.ZKProof = &schnorr.ZKProof{ + Alpha: origContent.ZKProof.Alpha, + T: corruptT, + } + + _, err := SignRound7(f.States[0], f.R5Bcast, corruptR6) + if err == nil { + t.Fatal("expected SignRound7 to fail with bad Schnorr proof, but got nil error") + } + if !strings.Contains(err.Error(), "schnorr Aj verify failed") { + t.Fatalf("expected 'schnorr Aj verify failed' error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("SignRound7 correctly rejected bad Schnorr proof: %v", err) +} + +// TestSignRound7RejectsBadVVerifyProof corrupts the ZKVProof T scalar +// in a Round6 message so that the V-verify fails (line 587-590). +func TestSignRound7RejectsBadVVerifyProof(t *testing.T) { + f := setupThroughRound6(t) + + corruptR6 := CloneBcastSlice(f.R6Bcast, CloneR6BcastMsg) + + // Add 1 to the ZKVProof T scalar for party 1. + origContent := corruptR6[1].Content.(*SignRound6Message) + N := tss.S256().Params().N + corruptT := new(big.Int).Add(origContent.ZKVProof.T, big.NewInt(1)) + corruptT.Mod(corruptT, N) + if corruptT.Sign() == 0 { + corruptT.SetInt64(1) + } + origContent.ZKVProof = &schnorr.ZKVProof{ + Alpha: origContent.ZKVProof.Alpha, + T: corruptT, + U: origContent.ZKVProof.U, + } + + _, err := SignRound7(f.States[0], f.R5Bcast, corruptR6) + if err == nil { + t.Fatal("expected SignRound7 to fail with bad ZKVProof, but got nil error") + } + if !strings.Contains(err.Error(), "vverify Vj failed") { + t.Fatalf("expected 'vverify Vj failed' error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("SignRound7 correctly rejected bad ZKVProof: %v", err) +} + +// --------------------------------------------------------------------------- +// SignRound9 negative tests +// --------------------------------------------------------------------------- + +// TestSignRound9RejectsBadDecommitment corrupts the decommitment in a Round8 +// message so that the Uj/Tj decommit check fails (line 654-656). +func TestSignRound9RejectsBadDecommitment(t *testing.T) { + f := setupThroughRound8(t) + + corruptR8 := CloneBcastSlice(f.R8Bcast, CloneR8BcastMsg) + + // Flip a bit in the randomness element of party 1's decommitment. + origContent := corruptR8[1].Content.(*SignRound8Message) + corruptD := make([]*big.Int, len(origContent.DeCommitment)) + for i, v := range origContent.DeCommitment { + corruptD[i] = new(big.Int).Set(v) + } + corruptD[0].Xor(corruptD[0], big.NewInt(1)) + origContent.DeCommitment = corruptD + + _, err := SignRound9(f.States[0], f.R7Bcast, corruptR8) + if err == nil { + t.Fatal("expected SignRound9 to fail with corrupted decommitment, but got nil error") + } + if !strings.Contains(err.Error(), "Uj/Tj decommit failed") { + t.Fatalf("expected 'Uj/Tj decommit failed' error, got: %v", err) + } + requireCulprit(t, err, 1) + t.Logf("SignRound9 correctly rejected bad decommitment: %v", err) +} diff --git a/tss-lib/ecdsa/signing/round_1.go b/tss-lib/ecdsa/signing/round_1.go deleted file mode 100644 index 31c853e..0000000 --- a/tss-lib/ecdsa/signing/round_1.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/mta" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -var zero = big.NewInt(0) - -// round 1 represents round 1 of the signing part of the GG18 ECDSA TSS spec (Gennaro, Goldfeder; 2018) -func newRound1(params *tss.Parameters, key *keygen.LocalPartySaveData, data *common.SignatureData, temp *localTempData, out chan<- tss.Message, end chan<- *common.SignatureData) tss.Round { - return &round1{ - &base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 1}, - } -} - -func (round *round1) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - - // Spec requires calculate H(M) here, - // but considered different blockchain use different hash function we accept the converted big.Int - // if this big.Int is not belongs to Zq, the client might not comply with common rule (for ECDSA): - // https://github.com/btcsuite/btcd/blob/c26ffa870fd817666a857af1bf6498fabba1ffe3/btcec/signature.go#L263 - if round.temp.m.Cmp(round.Params().EC().Params().N) >= 0 { - return round.WrapError(errors.New("hashed message is not valid")) - } - - round.number = 1 - round.started = true - round.resetOK() - round.temp.ssidNonce = new(big.Int).SetUint64(0) - ssid, err := round.getSSID() - if err != nil { - return round.WrapError(err) - } - round.temp.ssid = ssid - - k := common.GetRandomPositiveInt(round.Rand(), round.EC().Params().N) - gamma := common.GetRandomPositiveInt(round.Rand(), round.EC().Params().N) - - pointGamma := crypto.ScalarBaseMult(round.Params().EC(), gamma) - cmt := commitments.NewHashCommitment(round.Rand(), pointGamma.X(), pointGamma.Y()) - round.temp.k = k - round.temp.gamma = gamma - round.temp.pointGamma = pointGamma - round.temp.deCommit = cmt.D - - i := round.PartyID().Index - round.ok[i] = true - - for j, Pj := range round.Parties().IDs() { - if j == i { - continue - } - cA, pi, err := mta.AliceInit(round.Params().EC(), round.key.PaillierPKs[i], k, round.key.NTildej[j], round.key.H1j[j], round.key.H2j[j], round.Rand()) - if err != nil { - return round.WrapError(fmt.Errorf("failed to init mta: %v", err)) - } - r1msg1 := NewSignRound1Message1(Pj, round.PartyID(), cA, pi) - round.temp.cis[j] = cA - round.out <- r1msg1 - } - - r1msg2 := NewSignRound1Message2(round.PartyID(), cmt.C) - round.temp.signRound1Message2s[i] = r1msg2 - round.out <- r1msg2 - - return nil -} - -func (round *round1) Update() (bool, *tss.Error) { - for j, msg1 := range round.temp.signRound1Message1s { - if round.ok[j] { - continue - } - if msg1 == nil || !round.CanAccept(msg1) { - return false, nil - } - msg2 := round.temp.signRound1Message2s[j] - if msg2 == nil || !round.CanAccept(msg2) { - return false, nil - } - round.ok[j] = true - } - return true, nil -} - -func (round *round1) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound1Message1); ok { - return !msg.IsBroadcast() - } - if _, ok := msg.Content().(*SignRound1Message2); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round1) NextRound() tss.Round { - round.started = false - return &round2{round} -} - -// ----- // - -// helper to call into PrepareForSigning() -func (round *round1) prepare() error { - i := round.PartyID().Index - - xi := round.key.Xi - ks := round.key.Ks - bigXs := round.key.BigXj - - if round.temp.keyDerivationDelta != nil { - // adding the key derivation delta to the xi's - // Suppose x has shamir shares x_0, x_1, ..., x_n - // So x + D has shamir shares x_0 + D, x_1 + D, ..., x_n + D - mod := common.ModInt(round.Params().EC().Params().N) - xi = mod.Add(round.temp.keyDerivationDelta, xi) - round.key.Xi = xi - } - - if round.Threshold()+1 > len(ks) { - return fmt.Errorf("t+1=%d is not satisfied by the key count of %d", round.Threshold()+1, len(ks)) - } - wi, bigWs := PrepareForSigning(round.Params().EC(), i, len(ks), xi, ks, bigXs) - - round.temp.w = wi - round.temp.bigWs = bigWs - return nil -} diff --git a/tss-lib/ecdsa/signing/round_2.go b/tss-lib/ecdsa/signing/round_2.go deleted file mode 100644 index fa89ddd..0000000 --- a/tss-lib/ecdsa/signing/round_2.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - "sync" - - errorspkg "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/crypto/mta" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round2) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 2 - round.started = true - round.resetOK() - - i := round.PartyID().Index - round.ok[i] = true - - errChs := make(chan *tss.Error, (len(round.Parties().IDs())-1)*2) - wg := sync.WaitGroup{} - wg.Add((len(round.Parties().IDs()) - 1) * 2) - ContextI := append(round.temp.ssid, new(big.Int).SetUint64(uint64(i)).Bytes()...) - for j, Pj := range round.Parties().IDs() { - if j == i { - continue - } - // Bob_mid - go func(j int, Pj *tss.PartyID) { - defer wg.Done() - r1msg := round.temp.signRound1Message1s[j].Content().(*SignRound1Message1) - rangeProofAliceJ, err := r1msg.UnmarshalRangeProofAlice() - if err != nil { - errChs <- round.WrapError(errorspkg.Wrapf(err, "UnmarshalRangeProofAlice failed"), Pj) - return - } - beta, c1ji, _, pi1ji, err := mta.BobMid( - ContextI, - round.Parameters.EC(), - round.key.PaillierPKs[j], - rangeProofAliceJ, - round.temp.gamma, - r1msg.UnmarshalC(), - round.key.NTildej[j], - round.key.H1j[j], - round.key.H2j[j], - round.key.NTildej[i], - round.key.H1j[i], - round.key.H2j[i], - round.Rand(), - ) - // should be thread safe as these are pre-allocated - round.temp.betas[j] = beta - round.temp.c1jis[j] = c1ji - round.temp.pi1jis[j] = pi1ji - if err != nil { - errChs <- round.WrapError(err, Pj) - } - }(j, Pj) - // Bob_mid_wc - go func(j int, Pj *tss.PartyID) { - defer wg.Done() - r1msg := round.temp.signRound1Message1s[j].Content().(*SignRound1Message1) - rangeProofAliceJ, err := r1msg.UnmarshalRangeProofAlice() - if err != nil { - errChs <- round.WrapError(errorspkg.Wrapf(err, "UnmarshalRangeProofAlice failed"), Pj) - return - } - v, c2ji, _, pi2ji, err := mta.BobMidWC( - ContextI, - round.Parameters.EC(), - round.key.PaillierPKs[j], - rangeProofAliceJ, - round.temp.w, - r1msg.UnmarshalC(), - round.key.NTildej[j], - round.key.H1j[j], - round.key.H2j[j], - round.key.NTildej[i], - round.key.H1j[i], - round.key.H2j[i], - round.temp.bigWs[i], - round.Rand(), - ) - round.temp.vs[j] = v - round.temp.c2jis[j] = c2ji - round.temp.pi2jis[j] = pi2ji - if err != nil { - errChs <- round.WrapError(err, Pj) - } - }(j, Pj) - } - // consume error channels; wait for goroutines - wg.Wait() - close(errChs) - culprits := make([]*tss.PartyID, 0, len(round.Parties().IDs())) - for err := range errChs { - culprits = append(culprits, err.Culprits()...) - } - if len(culprits) > 0 { - return round.WrapError(errors.New("failed to calculate Bob_mid or Bob_mid_wc"), culprits...) - } - // create and send messages - for j, Pj := range round.Parties().IDs() { - if j == i { - continue - } - r2msg := NewSignRound2Message( - Pj, round.PartyID(), round.temp.c1jis[j], round.temp.pi1jis[j], round.temp.c2jis[j], round.temp.pi2jis[j]) - round.out <- r2msg - } - return nil -} - -func (round *round2) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound2Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round2) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound2Message); ok { - return !msg.IsBroadcast() - } - return false -} - -func (round *round2) NextRound() tss.Round { - round.started = false - return &round3{round} -} diff --git a/tss-lib/ecdsa/signing/round_3.go b/tss-lib/ecdsa/signing/round_3.go deleted file mode 100644 index ee038ab..0000000 --- a/tss-lib/ecdsa/signing/round_3.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - "sync" - - errorspkg "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto/mta" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round3) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 3 - round.started = true - round.resetOK() - - var alphas = make([]*big.Int, len(round.Parties().IDs())) - var us = make([]*big.Int, len(round.Parties().IDs())) - - i := round.PartyID().Index - - errChs := make(chan *tss.Error, (len(round.Parties().IDs())-1)*2) - wg := sync.WaitGroup{} - wg.Add((len(round.Parties().IDs()) - 1) * 2) - for j, Pj := range round.Parties().IDs() { - if j == i { - continue - } - ContextJ := append(round.temp.ssid, new(big.Int).SetUint64(uint64(j)).Bytes()...) - // Alice_end - go func(j int, Pj *tss.PartyID) { - defer wg.Done() - r2msg := round.temp.signRound2Messages[j].Content().(*SignRound2Message) - proofBob, err := r2msg.UnmarshalProofBob() - if err != nil { - errChs <- round.WrapError(errorspkg.Wrapf(err, "UnmarshalProofBob failed"), Pj) - return - } - alphaIj, err := mta.AliceEnd( - ContextJ, - round.Params().EC(), - round.key.PaillierPKs[i], - proofBob, - round.key.H1j[i], - round.key.H2j[i], - round.temp.cis[j], - new(big.Int).SetBytes(r2msg.GetC1()), - round.key.NTildej[i], - round.key.PaillierSK) - alphas[j] = alphaIj - if err != nil { - errChs <- round.WrapError(err, Pj) - } - }(j, Pj) - // Alice_end_wc - go func(j int, Pj *tss.PartyID) { - defer wg.Done() - r2msg := round.temp.signRound2Messages[j].Content().(*SignRound2Message) - proofBobWC, err := r2msg.UnmarshalProofBobWC(round.Parameters.EC()) - if err != nil { - errChs <- round.WrapError(errorspkg.Wrapf(err, "UnmarshalProofBobWC failed"), Pj) - return - } - uIj, err := mta.AliceEndWC( - ContextJ, - round.Params().EC(), - round.key.PaillierPKs[i], - proofBobWC, - round.temp.bigWs[j], - round.temp.cis[j], - new(big.Int).SetBytes(r2msg.GetC2()), - round.key.NTildej[i], - round.key.H1j[i], - round.key.H2j[i], - round.key.PaillierSK) - us[j] = uIj - if err != nil { - errChs <- round.WrapError(err, Pj) - } - }(j, Pj) - } - - // consume error channels; wait for goroutines - wg.Wait() - close(errChs) - culprits := make([]*tss.PartyID, 0, len(round.Parties().IDs())) - for err := range errChs { - culprits = append(culprits, err.Culprits()...) - } - if len(culprits) > 0 { - return round.WrapError(errors.New("failed to calculate Alice_end or Alice_end_wc"), culprits...) - } - - modN := common.ModInt(round.Params().EC().Params().N) - thelta := modN.Mul(round.temp.k, round.temp.gamma) - sigma := modN.Mul(round.temp.k, round.temp.w) - - for j := range round.Parties().IDs() { - if j == round.PartyID().Index { - continue - } - thelta = modN.Add(thelta, alphas[j].Add(alphas[j], round.temp.betas[j])) - sigma = modN.Add(sigma, us[j].Add(us[j], round.temp.vs[j])) - } - - round.temp.theta = thelta - round.temp.sigma = sigma - r3msg := NewSignRound3Message(round.PartyID(), thelta) - round.temp.signRound3Messages[round.PartyID().Index] = r3msg - round.out <- r3msg - - return nil -} - -func (round *round3) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound3Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round3) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound3Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round3) NextRound() tss.Round { - round.started = false - return &round4{round} -} diff --git a/tss-lib/ecdsa/signing/round_4.go b/tss-lib/ecdsa/signing/round_4.go deleted file mode 100644 index 8d12463..0000000 --- a/tss-lib/ecdsa/signing/round_4.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round4) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 4 - round.started = true - round.resetOK() - - theta := *round.temp.theta - thetaInverse := &theta - - modN := common.ModInt(round.Params().EC().Params().N) - - for j := range round.Parties().IDs() { - if j == round.PartyID().Index { - continue - } - r3msg := round.temp.signRound3Messages[j].Content().(*SignRound3Message) - theltaJ := r3msg.GetTheta() - thetaInverse = modN.Add(thetaInverse, new(big.Int).SetBytes(theltaJ)) - } - - // compute the multiplicative inverse thelta mod q - thetaInverse = modN.ModInverse(thetaInverse) - i := round.PartyID().Index - ContextI := append(round.temp.ssid, new(big.Int).SetUint64(uint64(i)).Bytes()...) - piGamma, err := schnorr.NewZKProof(ContextI, round.temp.gamma, round.temp.pointGamma, round.Rand()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewZKProof(gamma, bigGamma)")) - } - round.temp.thetaInverse = thetaInverse - r4msg := NewSignRound4Message(round.PartyID(), round.temp.deCommit, piGamma) - round.temp.signRound4Messages[round.PartyID().Index] = r4msg - round.out <- r4msg - - return nil -} - -func (round *round4) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound4Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round4) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound4Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round4) NextRound() tss.Round { - round.started = false - return &round5{round} -} diff --git a/tss-lib/ecdsa/signing/round_5.go b/tss-lib/ecdsa/signing/round_5.go deleted file mode 100644 index 3482ce9..0000000 --- a/tss-lib/ecdsa/signing/round_5.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round5) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 5 - round.started = true - round.resetOK() - - R := round.temp.pointGamma - for j, Pj := range round.Parties().IDs() { - if j == round.PartyID().Index { - continue - } - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - r1msg2 := round.temp.signRound1Message2s[j].Content().(*SignRound1Message2) - r4msg := round.temp.signRound4Messages[j].Content().(*SignRound4Message) - SCj, SDj := r1msg2.UnmarshalCommitment(), r4msg.UnmarshalDeCommitment() - cmtDeCmt := commitments.HashCommitDecommit{C: SCj, D: SDj} - ok, bigGammaJ := cmtDeCmt.DeCommit() - if !ok || len(bigGammaJ) != 2 { - return round.WrapError(errors.New("commitment verify failed"), Pj) - } - bigGammaJPoint, err := crypto.NewECPoint(round.Params().EC(), bigGammaJ[0], bigGammaJ[1]) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewECPoint(bigGammaJ)"), Pj) - } - proof, err := r4msg.UnmarshalZKProof(round.Params().EC()) - if err != nil { - return round.WrapError(errors.New("failed to unmarshal bigGamma proof"), Pj) - } - ok = proof.Verify(ContextJ, bigGammaJPoint) - if !ok { - return round.WrapError(errors.New("failed to prove bigGamma"), Pj) - } - R, err = R.Add(bigGammaJPoint) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "R.Add(bigGammaJ)"), Pj) - } - } - - R = R.ScalarMult(round.temp.thetaInverse) - N := round.Params().EC().Params().N - modN := common.ModInt(N) - rx := R.X() - ry := R.Y() - si := modN.Add(modN.Mul(round.temp.m, round.temp.k), modN.Mul(rx, round.temp.sigma)) - - // clear temp.w and temp.k from memory, lint ignore - round.temp.w = zero - round.temp.k = zero - - li := common.GetRandomPositiveInt(round.Rand(), N) // li - roI := common.GetRandomPositiveInt(round.Rand(), N) // pi - rToSi := R.ScalarMult(si) - liPoint := crypto.ScalarBaseMult(round.Params().EC(), li) - bigAi := crypto.ScalarBaseMult(round.Params().EC(), roI) - bigVi, err := rToSi.Add(liPoint) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "rToSi.Add(li)")) - } - - cmt := commitments.NewHashCommitment(round.Rand(), bigVi.X(), bigVi.Y(), bigAi.X(), bigAi.Y()) - r5msg := NewSignRound5Message(round.PartyID(), cmt.C) - round.temp.signRound5Messages[round.PartyID().Index] = r5msg - round.out <- r5msg - - round.temp.li = li - round.temp.bigAi = bigAi - round.temp.bigVi = bigVi - round.temp.roi = roI - round.temp.DPower = cmt.D - round.temp.si = si - round.temp.rx = rx - round.temp.ry = ry - round.temp.bigR = R - - return nil -} - -func (round *round5) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound5Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round5) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound5Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round5) NextRound() tss.Round { - round.started = false - return &round6{round} -} diff --git a/tss-lib/ecdsa/signing/round_6.go b/tss-lib/ecdsa/signing/round_6.go deleted file mode 100644 index 9de02e5..0000000 --- a/tss-lib/ecdsa/signing/round_6.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round6) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 6 - round.started = true - round.resetOK() - - i := round.PartyID().Index - ContextI := append(round.temp.ssid, new(big.Int).SetUint64(uint64(i)).Bytes()...) - piAi, err := schnorr.NewZKProof(ContextI, round.temp.roi, round.temp.bigAi, round.Rand()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewZKProof(roi, bigAi)")) - } - piV, err := schnorr.NewZKVProof(ContextI, round.temp.bigVi, round.temp.bigR, round.temp.si, round.temp.li, round.Rand()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewZKVProof(bigVi, bigR, si, li)")) - } - - r6msg := NewSignRound6Message(round.PartyID(), round.temp.DPower, piAi, piV) - round.temp.signRound6Messages[round.PartyID().Index] = r6msg - round.out <- r6msg - return nil -} - -func (round *round6) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound6Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round6) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound6Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round6) NextRound() tss.Round { - round.started = false - return &round7{round} -} diff --git a/tss-lib/ecdsa/signing/round_7.go b/tss-lib/ecdsa/signing/round_7.go deleted file mode 100644 index c037293..0000000 --- a/tss-lib/ecdsa/signing/round_7.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round7) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 7 - round.started = true - round.resetOK() - - bigVjs := make([]*crypto.ECPoint, len(round.Parties().IDs())) - bigAjs := make([]*crypto.ECPoint, len(round.Parties().IDs())) - for j, Pj := range round.Parties().IDs() { - if j == round.PartyID().Index { - continue - } - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - r5msg := round.temp.signRound5Messages[j].Content().(*SignRound5Message) - r6msg := round.temp.signRound6Messages[j].Content().(*SignRound6Message) - cj, dj := r5msg.UnmarshalCommitment(), r6msg.UnmarshalDeCommitment() - cmtDeCmt := commitments.HashCommitDecommit{C: cj, D: dj} - ok, values := cmtDeCmt.DeCommit() - if !ok || len(values) != 4 { - return round.WrapError(errors.New("de-commitment for bigVj and bigAj failed"), Pj) - } - bigVjX, bigVjY, bigAjX, bigAjY := values[0], values[1], values[2], values[3] - bigVj, err := crypto.NewECPoint(round.Params().EC(), bigVjX, bigVjY) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewECPoint(bigVj)"), Pj) - } - bigVjs[j] = bigVj - bigAj, err := crypto.NewECPoint(round.Params().EC(), bigAjX, bigAjY) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewECPoint(bigAj)"), Pj) - } - bigAjs[j] = bigAj - pijA, err := r6msg.UnmarshalZKProof(round.Params().EC()) - if err != nil || !pijA.Verify(ContextJ, bigAj) { - return round.WrapError(errors.New("schnorr verify for Aj failed"), Pj) - } - pijV, err := r6msg.UnmarshalZKVProof(round.Params().EC()) - if err != nil || !pijV.Verify(ContextJ, bigVj, round.temp.bigR) { - return round.WrapError(errors.New("vverify for Vj failed"), Pj) - } - } - - modN := common.ModInt(round.Params().EC().Params().N) - AX, AY := round.temp.bigAi.X(), round.temp.bigAi.Y() - minusM := modN.Sub(big.NewInt(0), round.temp.m) - gToMInvX, gToMInvY := round.Params().EC().ScalarBaseMult(minusM.Bytes()) - minusR := modN.Sub(big.NewInt(0), round.temp.rx) - yToRInvX, yToRInvY := round.Params().EC().ScalarMult(round.key.ECDSAPub.X(), round.key.ECDSAPub.Y(), minusR.Bytes()) - VX, VY := round.Params().EC().Add(gToMInvX, gToMInvY, yToRInvX, yToRInvY) - VX, VY = round.Params().EC().Add(VX, VY, round.temp.bigVi.X(), round.temp.bigVi.Y()) - - for j := range round.Parties().IDs() { - if j == round.PartyID().Index { - continue - } - VX, VY = round.Params().EC().Add(VX, VY, bigVjs[j].X(), bigVjs[j].Y()) - AX, AY = round.Params().EC().Add(AX, AY, bigAjs[j].X(), bigAjs[j].Y()) - } - - UiX, UiY := round.Params().EC().ScalarMult(VX, VY, round.temp.roi.Bytes()) - TiX, TiY := round.Params().EC().ScalarMult(AX, AY, round.temp.li.Bytes()) - round.temp.Ui = crypto.NewECPointNoCurveCheck(round.Params().EC(), UiX, UiY) - round.temp.Ti = crypto.NewECPointNoCurveCheck(round.Params().EC(), TiX, TiY) - cmt := commitments.NewHashCommitment(round.Rand(), UiX, UiY, TiX, TiY) - r7msg := NewSignRound7Message(round.PartyID(), cmt.C) - round.temp.signRound7Messages[round.PartyID().Index] = r7msg - round.out <- r7msg - round.temp.DTelda = cmt.D - - return nil -} - -func (round *round7) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound7Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round7) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound7Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round7) NextRound() tss.Round { - round.started = false - return &round8{round} -} diff --git a/tss-lib/ecdsa/signing/round_8.go b/tss-lib/ecdsa/signing/round_8.go deleted file mode 100644 index 7f36864..0000000 --- a/tss-lib/ecdsa/signing/round_8.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round8) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 8 - round.started = true - round.resetOK() - - r8msg := NewSignRound8Message(round.PartyID(), round.temp.DTelda) - round.temp.signRound8Messages[round.PartyID().Index] = r8msg - round.out <- r8msg - - return nil -} - -func (round *round8) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound8Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round8) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound8Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round8) NextRound() tss.Round { - round.started = false - return &round9{round} -} diff --git a/tss-lib/ecdsa/signing/round_9.go b/tss-lib/ecdsa/signing/round_9.go deleted file mode 100644 index a2b3083..0000000 --- a/tss-lib/ecdsa/signing/round_9.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round9) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 9 - round.started = true - round.resetOK() - - UX, UY := round.temp.Ui.X(), round.temp.Ui.Y() - TX, TY := round.temp.Ti.X(), round.temp.Ti.Y() - for j, Pj := range round.Parties().IDs() { - if j == round.PartyID().Index { - continue - } - - r7msg := round.temp.signRound7Messages[j].Content().(*SignRound7Message) - r8msg := round.temp.signRound8Messages[j].Content().(*SignRound8Message) - cj, dj := r7msg.UnmarshalCommitment(), r8msg.UnmarshalDeCommitment() - cmt := commitments.HashCommitDecommit{C: cj, D: dj} - ok, values := cmt.DeCommit() - if !ok && len(values) != 4 { - return round.WrapError(errors.New("de-commitment for bigVj and bigAj failed"), Pj) - } - UjX, UjY, TjX, TjY := values[0], values[1], values[2], values[3] - UX, UY = round.Params().EC().Add(UX, UY, UjX, UjY) - TX, TY = round.Params().EC().Add(TX, TY, TjX, TjY) - } - if UX.Cmp(TX) != 0 || UY.Cmp(TY) != 0 { - return round.WrapError(errors.New("U doesn't equal T"), round.PartyID()) - } - - r9msg := NewSignRound9Message(round.PartyID(), round.temp.si) - round.temp.signRound9Messages[round.PartyID().Index] = r9msg - round.out <- r9msg - return nil -} - -func (round *round9) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound9Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round9) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound9Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round9) NextRound() tss.Round { - round.started = false - return &finalization{round} -} diff --git a/tss-lib/ecdsa/signing/round_fn.go b/tss-lib/ecdsa/signing/round_fn.go new file mode 100644 index 0000000..0d275be --- /dev/null +++ b/tss-lib/ecdsa/signing/round_fn.go @@ -0,0 +1,752 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "bytes" + "context" + "crypto/ecdsa" + "errors" + "fmt" + "math/big" + "sync" + + errorspkg "github.com/pkg/errors" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// getSigningSSID computes the SSID for signing rounds. +func getSigningSSID(params *tss.Parameters, key *keygen.LocalPartySaveData, temp *localTempData, roundNumber int) ([]byte, error) { + ssidList := []*big.Int{ + new(big.Int).SetBytes([]byte("ecdsa-signing")), + params.EC().Params().P, params.EC().Params().N, + params.EC().Params().B, params.EC().Params().Gx, + params.EC().Params().Gy, + } + ssidList = append(ssidList, params.Parties().IDs().Keys()...) + BigXjList, err := crypto.FlattenECPoints(key.BigXj) + if err != nil { + return nil, fmt.Errorf("flatten ec points: %w", err) + } + ssidList = append(ssidList, BigXjList...) + ssidList = append(ssidList, key.NTildej...) + ssidList = append(ssidList, key.H1j...) + ssidList = append(ssidList, key.H2j...) + ssidList = append(ssidList, big.NewInt(int64(params.PartyCount()))) + ssidList = append(ssidList, big.NewInt(int64(params.Threshold()))) + ssidList = append(ssidList, big.NewInt(int64(roundNumber))) + ssidList = append(ssidList, temp.ssidNonce) + if cid := params.CeremonyID(); len(cid) > 0 { + ssidList = append(ssidList, new(big.Int).SetBytes(cid)) + } + if temp.m != nil { + ssidList = append(ssidList, temp.m) + } + return common.SHA512_256i(ssidList...).Bytes(), nil +} + +// SignRound1 initializes the signing state and produces MtA messages. +// +// msg is the hash to sign (must be in [0, N)). +// key is the party's saved keygen data. +// keyDerivationDelta is optional HD derivation delta (nil for no derivation). +// fullBytesLen is the byte length for message padding (0 for default). +func SignRound1(params *tss.Parameters, key keygen.LocalPartySaveData, msg *big.Int, keyDerivationDelta *big.Int, fullBytesLen int) (*SigningState, *SignRoundOutput, error) { + n := params.PartyCount() + temp := &localTempData{ + localMessageStore: localMessageStore{ + signRound1Message1s: make([]*tss.Message, n), + signRound1Message2s: make([]*tss.Message, n), + signRound2Messages: make([]*tss.Message, n), + signRound3Messages: make([]*tss.Message, n), + signRound4Messages: make([]*tss.Message, n), + signRound5Messages: make([]*tss.Message, n), + signRound6Messages: make([]*tss.Message, n), + signRound7Messages: make([]*tss.Message, n), + signRound8Messages: make([]*tss.Message, n), + signRound9Messages: make([]*tss.Message, n), + }, + cis: make([]*big.Int, n), + bigWs: make([]*crypto.ECPoint, n), + m: msg, + fullBytesLen: fullBytesLen, + keyDerivationDelta: keyDerivationDelta, + betas: make([]*big.Int, n), + c1jis: make([]*big.Int, n), + c2jis: make([]*big.Int, n), + vs: make([]*big.Int, n), + pi1jis: make([]*mta.ProofBob, n), + pi2jis: make([]*mta.ProofBobWC, n), + } + data := &SignatureData{} + + // Validate message + if msg.Sign() < 0 || msg.Cmp(params.EC().Params().N) >= 0 { + return nil, nil, errors.New("hashed message is not valid") + } + + // Auto-subset: if the key has more parties than the signing + // committee (threshold signing with a subset of keygen parties), + // trim the key data to only the signing parties. This avoids + // requiring callers to call BuildLocalSaveDataSubset manually. + if len(key.Ks) > params.PartyCount() { + key = keygen.BuildLocalSaveDataSubset(key, params.Parties().IDs()) + } + if len(key.Ks) != params.PartyCount() { + return nil, nil, fmt.Errorf("key count %d != party count %d after subset", len(key.Ks), params.PartyCount()) + } + if params.Threshold()+1 > len(key.Ks) { + return nil, nil, fmt.Errorf("t+1=%d > key count %d", params.Threshold()+1, len(key.Ks)) + } + + // Prepare (Lagrange coefficients) + i := params.PartyID().Index + xi := key.Xi + if keyDerivationDelta != nil { + mod := common.ModInt(params.EC().Params().N) + xi = mod.Add(keyDerivationDelta, xi) + } + wi, bigWs := PrepareForSigning(params.EC(), i, len(key.Ks), xi, key.Ks, key.BigXj) + temp.w = wi + temp.bigWs = bigWs + + // SSID + temp.ssidNonce = new(big.Int).SetUint64(uint64(params.SSIDNonce())) + ssid, err := getSigningSSID(params, &key, temp, 1) + if err != nil { + return nil, nil, err + } + temp.ssid = ssid + + // Generate k, gamma + k := common.GetRandomPositiveInt(params.Rand(), params.EC().Params().N) + gamma := common.GetRandomPositiveInt(params.Rand(), params.EC().Params().N) + pointGamma := crypto.ScalarBaseMult(params.EC(), gamma) + cmt := commitments.NewHashCommitment(params.Rand(), pointGamma.X(), pointGamma.Y()) + temp.k = k + temp.gamma = gamma + temp.pointGamma = pointGamma + temp.deCommit = cmt.D + + // MtA init for each peer + out := &SignRoundOutput{} + ContextI := common.AppendBigIntToBytesSlice(ssid, new(big.Int).SetInt64(int64(i))) + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + cA, pi, err := mta.AliceInit(ContextI, params.EC(), key.PaillierPKs[i], k, + key.NTildej[j], key.H1j[j], key.H2j[j], params.Rand()) + if err != nil { + return nil, nil, fmt.Errorf("mta AliceInit: %w", err) + } + r1msg1 := NewSignRound1Message1(Pj, params.PartyID(), cA, pi) + temp.cis[j] = cA + out.Messages = append(out.Messages, r1msg1) + } + + r1msg2 := NewSignRound1Message2(params.PartyID(), cmt.C) + temp.signRound1Message2s[i] = r1msg2 + out.Messages = append(out.Messages, r1msg2) + + state := &SigningState{params: params, key: &key, data: data, temp: temp} + return state, out, nil +} + +// SignRound2 processes round 1 messages and runs MtA Bob. +// +// r1p2p[j] is party j's SignRound1Message1 (P2P). +// r1bcast[j] is party j's SignRound1Message2 (broadcast). +func SignRound2(ctx context.Context, state *SigningState, r1p2p, r1bcast []*tss.Message) (*SignRoundOutput, error) { + params, key, temp := state.params, state.key, state.temp + tss.MergeMsgs(temp.signRound1Message1s, r1p2p) + tss.MergeMsgs(temp.signRound1Message2s, r1bcast) + + i := params.PartyID().Index + + // ReceiverID check + myKey := params.PartyID().KeyInt().Bytes() + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + r1msg := r1p2p[j].Content.(*SignRound1Message1) + if !bytes.Equal(r1msg.ReceiverID, myKey) { + return nil, tss.NewError(errors.New("receiverId mismatch"), TaskName, 2, params.PartyID(), Pj) + } + } + + n := len(params.Parties().IDs()) + errsMid := make([]*tss.Error, n) + errsMidWC := make([]*tss.Error, n) + gctx, gcancel := context.WithCancel(ctx) + defer gcancel() + wg := sync.WaitGroup{} + wg.Add((n - 1) * 2) + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(i))) + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + // Bob_mid + go func(j int, Pj *tss.PartyID) { + defer wg.Done() + if gctx.Err() != nil { + return + } + r1msg := r1p2p[j].Content.(*SignRound1Message1) + rangeProofAliceJ := r1msg.RangeProofAlice + if rangeProofAliceJ == nil { + errsMid[j] = tss.NewError(errorspkg.New("RangeProofAlice missing"), TaskName, 2, params.PartyID(), Pj) + gcancel() + return + } + if gctx.Err() != nil { + return + } + AliceContextJ := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(j))) + beta, c1ji, _, pi1ji, err := mta.BobMid( + AliceContextJ, ContextI, params.EC(), key.PaillierPKs[j], + rangeProofAliceJ, temp.gamma, r1msg.C, + key.NTildej[j], key.H1j[j], key.H2j[j], + key.NTildej[i], key.H1j[i], key.H2j[i], params.Rand()) + if err != nil { + errsMid[j] = tss.NewError(err, TaskName, 2, params.PartyID(), Pj) + gcancel() + return + } + temp.betas[j] = beta + temp.c1jis[j] = c1ji + temp.pi1jis[j] = pi1ji + }(j, Pj) + // Bob_mid_wc + go func(j int, Pj *tss.PartyID) { + defer wg.Done() + if gctx.Err() != nil { + return + } + r1msg := r1p2p[j].Content.(*SignRound1Message1) + rangeProofAliceJ := r1msg.RangeProofAlice + if rangeProofAliceJ == nil { + errsMidWC[j] = tss.NewError(errorspkg.New("RangeProofAlice missing"), TaskName, 2, params.PartyID(), Pj) + gcancel() + return + } + if gctx.Err() != nil { + return + } + AliceContextJ := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(j))) + v, c2ji, _, pi2ji, err := mta.BobMidWC( + AliceContextJ, ContextI, params.EC(), key.PaillierPKs[j], + rangeProofAliceJ, temp.w, r1msg.C, + key.NTildej[j], key.H1j[j], key.H2j[j], + key.NTildej[i], key.H1j[i], key.H2j[i], + temp.bigWs[i], params.Rand()) + if err != nil { + errsMidWC[j] = tss.NewError(err, TaskName, 2, params.PartyID(), Pj) + gcancel() + return + } + temp.vs[j] = v + temp.c2jis[j] = c2ji + temp.pi2jis[j] = pi2ji + }(j, Pj) + } + wg.Wait() + if err := ctx.Err(); err != nil { + return nil, err + } + for j := range n { + if errsMid[j] != nil { + return nil, errsMid[j] + } + if errsMidWC[j] != nil { + return nil, errsMidWC[j] + } + } + + out := &SignRoundOutput{} + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + r2msg := NewSignRound2Message(Pj, params.PartyID(), + temp.c1jis[j], temp.pi1jis[j], temp.c2jis[j], temp.pi2jis[j]) + out.Messages = append(out.Messages, r2msg) + } + return out, nil +} + +// SignRound3 processes round 2 MtA responses and computes theta/sigma. +func SignRound3(ctx context.Context, state *SigningState, r2p2p []*tss.Message) (*SignRoundOutput, error) { + params, key, temp := state.params, state.key, state.temp + tss.MergeMsgs(temp.signRound2Messages, r2p2p) + + n := len(params.Parties().IDs()) + alphas := make([]*big.Int, n) + us := make([]*big.Int, n) + i := params.PartyID().Index + + // ReceiverID check + myKey := params.PartyID().KeyInt().Bytes() + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + r2msg := r2p2p[j].Content.(*SignRound2Message) + if !bytes.Equal(r2msg.ReceiverID, myKey) { + return nil, tss.NewError(errors.New("receiverId mismatch"), TaskName, 3, params.PartyID(), Pj) + } + } + + errsAlice := make([]*tss.Error, n) + errsAliceWC := make([]*tss.Error, n) + gctx, gcancel := context.WithCancel(ctx) + defer gcancel() + wg := sync.WaitGroup{} + wg.Add((n - 1) * 2) + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(j))) + go func(j int, Pj *tss.PartyID) { + defer wg.Done() + if gctx.Err() != nil { + return + } + r2msg := r2p2p[j].Content.(*SignRound2Message) + proofBob := r2msg.ProofBob + if proofBob == nil { + errsAlice[j] = tss.NewError(errorspkg.New("ProofBob missing"), TaskName, 3, params.PartyID(), Pj) + gcancel() + return + } + if gctx.Err() != nil { + return + } + alphaIj, err := mta.AliceEnd(ContextJ, params.EC(), key.PaillierPKs[i], + proofBob, key.H1j[i], key.H2j[i], temp.cis[j], + r2msg.C1, key.NTildej[i], key.PaillierSK) + if err != nil { + errsAlice[j] = tss.NewError(err, TaskName, 3, params.PartyID(), Pj) + gcancel() + return + } + alphas[j] = alphaIj + }(j, Pj) + go func(j int, Pj *tss.PartyID) { + defer wg.Done() + if gctx.Err() != nil { + return + } + r2msg := r2p2p[j].Content.(*SignRound2Message) + proofBobWC := r2msg.ProofBobWC + if proofBobWC == nil { + errsAliceWC[j] = tss.NewError(errorspkg.New("ProofBobWC missing"), TaskName, 3, params.PartyID(), Pj) + gcancel() + return + } + if gctx.Err() != nil { + return + } + uIj, err := mta.AliceEndWC(ContextJ, params.EC(), key.PaillierPKs[i], + proofBobWC, temp.bigWs[j], temp.cis[j], + r2msg.C2, key.NTildej[i], + key.H1j[i], key.H2j[i], key.PaillierSK) + if err != nil { + errsAliceWC[j] = tss.NewError(err, TaskName, 3, params.PartyID(), Pj) + gcancel() + return + } + us[j] = uIj + }(j, Pj) + } + wg.Wait() + if err := ctx.Err(); err != nil { + return nil, err + } + for j := range n { + if errsAlice[j] != nil { + return nil, errsAlice[j] + } + if errsAliceWC[j] != nil { + return nil, errsAliceWC[j] + } + } + + modN := common.ModInt(params.EC().Params().N) + theta := modN.Mul(temp.k, temp.gamma) + sigma := modN.Mul(temp.k, temp.w) + for j := range params.Parties().IDs() { + if j == i { + continue + } + theta = modN.Add(theta, new(big.Int).Add(alphas[j], temp.betas[j])) + sigma = modN.Add(sigma, new(big.Int).Add(us[j], temp.vs[j])) + } + temp.theta = theta + temp.sigma = sigma + + r3msg := NewSignRound3Message(params.PartyID(), theta) + temp.signRound3Messages[i] = r3msg + return &SignRoundOutput{Messages: []*tss.Message{r3msg}}, nil +} + +// SignRound4 computes thetaInverse and Schnorr proof for gamma. +func SignRound4(state *SigningState, r3bcast []*tss.Message) (*SignRoundOutput, error) { + params, temp := state.params, state.temp + tss.MergeMsgs(temp.signRound3Messages, r3bcast) + + theta := new(big.Int).Set(temp.theta) + modN := common.ModInt(params.EC().Params().N) + i := params.PartyID().Index + + for j := range params.Parties().IDs() { + if j == i { + continue + } + r3msg := r3bcast[j].Content.(*SignRound3Message) + theta = modN.Add(theta, r3msg.Theta) + } + thetaInverse := modN.ModInverse(theta) + if thetaInverse == nil { + return nil, errors.New("theta is zero") + } + + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(i))) + piGamma, err := schnorr.NewZKProof(ContextI, temp.gamma, temp.pointGamma, params.Rand()) + if err != nil { + return nil, errorspkg.Wrapf(err, "NewZKProof(gamma, bigGamma)") + } + temp.thetaInverse = thetaInverse + + r4msg := NewSignRound4Message(params.PartyID(), temp.deCommit, piGamma) + temp.signRound4Messages[i] = r4msg + return &SignRoundOutput{Messages: []*tss.Message{r4msg}}, nil +} + +// SignRound5 verifies commitments, computes R, and produces blinding. +func SignRound5(state *SigningState, r4bcast []*tss.Message) (*SignRoundOutput, error) { + params, temp := state.params, state.temp + tss.MergeMsgs(temp.signRound4Messages, r4bcast) + + i := params.PartyID().Index + R := temp.pointGamma + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + r1msg2 := temp.signRound1Message2s[j].Content.(*SignRound1Message2) + r4msg := r4bcast[j].Content.(*SignRound4Message) + SCj, SDj := r1msg2.Commitment, r4msg.DeCommitment + cmtDeCmt := commitments.HashCommitDecommit{C: SCj, D: SDj} + ok, bigGammaJ := cmtDeCmt.DeCommit() + if !ok || len(bigGammaJ) != 2 { + return nil, tss.NewError(errors.New("commitment verify failed"), TaskName, 5, params.PartyID(), Pj) + } + bigGammaJPoint, err := crypto.NewECPoint(params.EC(), bigGammaJ[0], bigGammaJ[1]) + if err != nil { + return nil, tss.NewError(err, TaskName, 5, params.PartyID(), Pj) + } + proof := r4msg.ZKProof + if proof == nil { + return nil, tss.NewError(errors.New("bigGamma proof missing"), TaskName, 5, params.PartyID(), Pj) + } + if ok = proof.Verify(ContextJ, bigGammaJPoint); !ok { + return nil, tss.NewError(errors.New("bigGamma proof verify failed"), TaskName, 5, params.PartyID(), Pj) + } + var err2 error + R, err2 = R.Add(bigGammaJPoint) + if err2 != nil { + return nil, tss.NewError(err2, TaskName, 5, params.PartyID(), Pj) + } + } + + if R.IsIdentity() { + return nil, errors.New("sum of gamma points is identity") + } + R = R.ScalarMult(temp.thetaInverse) + if R.IsIdentity() { + return nil, errors.New("r is identity after theta-inverse") + } + + N := params.EC().Params().N + modN := common.ModInt(N) + rx, ry := R.X(), R.Y() + if new(big.Int).Mod(rx, N).Sign() == 0 { + return nil, errors.New("r component is zero") + } + + si := modN.Add(modN.Mul(temp.m, temp.k), modN.Mul(rx, temp.sigma)) + if si.Sign() == 0 { + return nil, errors.New("si is zero") + } + + // Clear secrets + temp.w = new(big.Int) + temp.k = new(big.Int) + temp.gamma = new(big.Int) + temp.sigma = new(big.Int) + + li := common.GetRandomPositiveInt(params.Rand(), N) + roI := common.GetRandomPositiveInt(params.Rand(), N) + rToSi := R.ScalarMult(si) + liPoint := crypto.ScalarBaseMult(params.EC(), li) + bigAi := crypto.ScalarBaseMult(params.EC(), roI) + bigVi, err := rToSi.Add(liPoint) + if err != nil { + return nil, fmt.Errorf("round 5 compute bigVi: %w", err) + } + + cmt := commitments.NewHashCommitment(params.Rand(), bigVi.X(), bigVi.Y(), bigAi.X(), bigAi.Y()) + r5msg := NewSignRound5Message(params.PartyID(), cmt.C) + temp.signRound5Messages[i] = r5msg + temp.li = li + temp.bigAi = bigAi + temp.bigVi = bigVi + temp.roi = roI + temp.DPower = cmt.D + temp.si = si + temp.rx = rx + temp.ry = ry + temp.bigR = R + + return &SignRoundOutput{Messages: []*tss.Message{r5msg}}, nil +} + +// SignRound6 produces Schnorr proofs for the blinding values. +func SignRound6(state *SigningState) (*SignRoundOutput, error) { + params, temp := state.params, state.temp + i := params.PartyID().Index + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(i))) + + piAi, err := schnorr.NewZKProof(ContextI, temp.roi, temp.bigAi, params.Rand()) + if err != nil { + return nil, errorspkg.Wrapf(err, "NewZKProof(roi, bigAi)") + } + piV, err := schnorr.NewZKVProof(ContextI, temp.bigVi, temp.bigR, temp.si, temp.li, params.Rand()) + if err != nil { + return nil, errorspkg.Wrapf(err, "NewZKVProof") + } + + r6msg := NewSignRound6Message(params.PartyID(), temp.DPower, piAi, piV) + temp.signRound6Messages[i] = r6msg + return &SignRoundOutput{Messages: []*tss.Message{r6msg}}, nil +} + +// SignRound7 verifies blinding proofs, computes Ui/Ti, and commits. +func SignRound7(state *SigningState, r5bcast, r6bcast []*tss.Message) (*SignRoundOutput, error) { + params, key, temp := state.params, state.key, state.temp + tss.MergeMsgs(temp.signRound5Messages, r5bcast) + tss.MergeMsgs(temp.signRound6Messages, r6bcast) + + i := params.PartyID().Index + bigVjs := make([]*crypto.ECPoint, len(params.Parties().IDs())) + bigAjs := make([]*crypto.ECPoint, len(params.Parties().IDs())) + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + r5msg := r5bcast[j].Content.(*SignRound5Message) + r6msg := r6bcast[j].Content.(*SignRound6Message) + cj, dj := r5msg.Commitment, r6msg.DeCommitment + cmtDeCmt := commitments.HashCommitDecommit{C: cj, D: dj} + ok, values := cmtDeCmt.DeCommit() + if !ok || len(values) != 4 { + return nil, tss.NewError(errors.New("de-commitment failed"), TaskName, 7, params.PartyID(), Pj) + } + bigVj, err := crypto.NewECPoint(params.EC(), values[0], values[1]) + if err != nil { + return nil, tss.NewError(err, TaskName, 7, params.PartyID(), Pj) + } + if bigVj.IsIdentity() { + return nil, tss.NewError(errors.New("bigVj is identity"), TaskName, 7, params.PartyID(), Pj) + } + bigVjs[j] = bigVj + bigAj, err := crypto.NewECPoint(params.EC(), values[2], values[3]) + if err != nil { + return nil, tss.NewError(err, TaskName, 7, params.PartyID(), Pj) + } + if bigAj.IsIdentity() { + return nil, tss.NewError(errors.New("bigAj is identity"), TaskName, 7, params.PartyID(), Pj) + } + bigAjs[j] = bigAj + pijA := r6msg.ZKProof + if pijA == nil || !pijA.Verify(ContextJ, bigAj) { + return nil, tss.NewError(errors.New("schnorr Aj verify failed"), TaskName, 7, params.PartyID(), Pj) + } + pijV := r6msg.ZKVProof + if pijV == nil || !pijV.Verify(ContextJ, bigVj, temp.bigR) { + return nil, tss.NewError(errors.New("vverify Vj failed"), TaskName, 7, params.PartyID(), Pj) + } + } + + modN := common.ModInt(params.EC().Params().N) + AX, AY := temp.bigAi.X(), temp.bigAi.Y() + minusM := modN.Sub(big.NewInt(0), temp.m) + gToMInvX, gToMInvY := params.EC().ScalarBaseMult(minusM.Bytes()) + minusR := modN.Sub(big.NewInt(0), temp.rx) + yToRInvX, yToRInvY := params.EC().ScalarMult(key.ECDSAPub.X(), key.ECDSAPub.Y(), minusR.Bytes()) + VX, VY := params.EC().Add(gToMInvX, gToMInvY, yToRInvX, yToRInvY) + VX, VY = params.EC().Add(VX, VY, temp.bigVi.X(), temp.bigVi.Y()) + for j := range params.Parties().IDs() { + if j == i { + continue + } + VX, VY = params.EC().Add(VX, VY, bigVjs[j].X(), bigVjs[j].Y()) + AX, AY = params.EC().Add(AX, AY, bigAjs[j].X(), bigAjs[j].Y()) + } + + UiX, UiY := params.EC().ScalarMult(VX, VY, temp.roi.Bytes()) + TiX, TiY := params.EC().ScalarMult(AX, AY, temp.li.Bytes()) + Ui, err := crypto.NewECPoint(params.EC(), UiX, UiY) + if err != nil { + return nil, fmt.Errorf("round 7 compute Ui: %w", err) + } + Ti, err := crypto.NewECPoint(params.EC(), TiX, TiY) + if err != nil { + return nil, fmt.Errorf("round 7 compute Ti: %w", err) + } + temp.Ui = Ui + temp.Ti = Ti + cmt := commitments.NewHashCommitment(params.Rand(), UiX, UiY, TiX, TiY) + r7msg := NewSignRound7Message(params.PartyID(), cmt.C) + temp.signRound7Messages[i] = r7msg + temp.DTelda = cmt.D + return &SignRoundOutput{Messages: []*tss.Message{r7msg}}, nil +} + +// SignRound8 decommits Ui/Ti. +func SignRound8(state *SigningState) (*SignRoundOutput, error) { + params, temp := state.params, state.temp + i := params.PartyID().Index + r8msg := NewSignRound8Message(params.PartyID(), temp.DTelda) + temp.signRound8Messages[i] = r8msg + return &SignRoundOutput{Messages: []*tss.Message{r8msg}}, nil +} + +// SignRound9 verifies Ui==Ti consistency and reveals si. +func SignRound9(state *SigningState, r7bcast, r8bcast []*tss.Message) (*SignRoundOutput, error) { + params, temp := state.params, state.temp + tss.MergeMsgs(temp.signRound7Messages, r7bcast) + tss.MergeMsgs(temp.signRound8Messages, r8bcast) + + i := params.PartyID().Index + UX, UY := temp.Ui.X(), temp.Ui.Y() + TX, TY := temp.Ti.X(), temp.Ti.Y() + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + r7msg := r7bcast[j].Content.(*SignRound7Message) + r8msg := r8bcast[j].Content.(*SignRound8Message) + cj, dj := r7msg.Commitment, r8msg.DeCommitment + cmt := commitments.HashCommitDecommit{C: cj, D: dj} + ok, values := cmt.DeCommit() + if !ok || len(values) != 4 { + return nil, tss.NewError(errors.New("Uj/Tj decommit failed"), TaskName, 9, params.PartyID(), Pj) + } + Uj, err := crypto.NewECPoint(params.EC(), values[0], values[1]) + if err != nil { + return nil, tss.NewError(err, TaskName, 9, params.PartyID(), Pj) + } + if Uj.IsIdentity() { + return nil, tss.NewError(errors.New("uj is identity"), TaskName, 9, params.PartyID(), Pj) + } + Tj, err := crypto.NewECPoint(params.EC(), values[2], values[3]) + if err != nil { + return nil, tss.NewError(err, TaskName, 9, params.PartyID(), Pj) + } + if Tj.IsIdentity() { + return nil, tss.NewError(errors.New("tj is identity"), TaskName, 9, params.PartyID(), Pj) + } + UX, UY = params.EC().Add(UX, UY, values[0], values[1]) + TX, TY = params.EC().Add(TX, TY, values[2], values[3]) + } + if UX.Cmp(TX) != 0 || UY.Cmp(TY) != 0 { + return nil, errors.New("u != t: signature share inconsistency") + } + + r9msg := NewSignRound9Message(params.PartyID(), temp.si) + temp.signRound9Messages[i] = r9msg + return &SignRoundOutput{Messages: []*tss.Message{r9msg}}, nil +} + +// SignFinalize collects partial signatures, aggregates S, normalizes, +// and verifies the final ECDSA signature. +func SignFinalize(state *SigningState, r9bcast []*tss.Message) (*SignRoundOutput, error) { + params, key, temp, data := state.params, state.key, state.temp, state.data + tss.MergeMsgs(temp.signRound9Messages, r9bcast) + + sumS := new(big.Int).Set(temp.si) + modN := common.ModInt(params.EC().Params().N) + N := params.EC().Params().N + i := params.PartyID().Index + + for j := range params.Parties().IDs() { + if j == i { + continue + } + r9msg := r9bcast[j].Content.(*SignRound9Message) + sj := r9msg.S + if sj.Sign() < 0 || sj.Cmp(N) >= 0 { + return nil, fmt.Errorf("party %d sent s_i outside [0, N)", j) + } + sumS = modN.Add(sumS, sj) + } + if sumS.Sign() == 0 { + return nil, errors.New("accumulated S is zero") + } + + recid := 0 + if temp.rx.Cmp(N) > 0 { + recid = 2 + } + if temp.ry.Bit(0) != 0 { + recid |= 1 + } + + // Low-S normalization + secp256k1halfN := new(big.Int).Rsh(N, 1) + if sumS.Cmp(secp256k1halfN) > 0 { + sumS.Sub(N, sumS) + recid ^= 1 + } + + bitSizeInBytes := (params.EC().Params().BitSize + 7) / 8 + data.R = padToLengthBytesInPlace(temp.rx.Bytes(), bitSizeInBytes) + data.S = padToLengthBytesInPlace(sumS.Bytes(), bitSizeInBytes) + data.Signature = append(data.R, data.S...) + data.SignatureRecovery = []byte{byte(recid)} + if temp.fullBytesLen == 0 { + data.M = temp.m.Bytes() + } else { + mBytes := make([]byte, temp.fullBytesLen) + temp.m.FillBytes(mBytes) + data.M = mBytes + } + + pk := ecdsa.PublicKey{ + Curve: params.EC(), + X: key.ECDSAPub.X(), + Y: key.ECDSAPub.Y(), + } + if ok := ecdsa.Verify(&pk, data.M, temp.rx, sumS); !ok { + return nil, errors.New("signature verification failed") + } + + return &SignRoundOutput{Signature: data}, nil +} diff --git a/tss-lib/ecdsa/signing/round_fn_test.go b/tss-lib/ecdsa/signing/round_fn_test.go new file mode 100644 index 0000000..e47750b --- /dev/null +++ b/tss-lib/ecdsa/signing/round_fn_test.go @@ -0,0 +1,623 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/testutil" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestRoundFnSignThreeParties runs keygen + signing using pure round +// functions for both. Verifies the signature with ecdsa.Verify. +func TestRoundFnSignThreeParties(t *testing.T) { + const n = 3 + const threshold = 1 // 2-of-3 + + // -- Keygen first -- + preParams := testutil.LoadPreParams(t, n) + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + } + for i := 0; i < n; i++ { + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + saves[i] = *out.Save + } + t.Logf("keygen done: ECDSAPub = (%x, %x)", saves[0].ECDSAPub.X(), saves[0].ECDSAPub.Y()) + + // -- Sign -- + msgHash := sha256.Sum256([]byte("test message")) + m := new(big.Int).SetBytes(msgHash[:]) + + sigStates := make([]*SigningState, n) + sigR1P2P := make([][]*tss.Message, n) + sigR1Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + sigR1P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := SignRound1(params, saves[i], m, nil, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + sigStates[i] = st + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + sigR1Bcast[i] = pm + } else { + for _, to := range pm.To { + sigR1P2P[to.Index][i] = pm + } + } + } + } + + // Round 2 + sigR2P2P := make([][]*tss.Message, n) + for i := 0; i < n; i++ { + sigR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := SignRound2(context.Background(), sigStates[i], sigR1P2P[i], sigR1Bcast) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + for _, to := range pm.To { + sigR2P2P[to.Index][i] = pm + } + } + } + + // Round 3 + sigR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound3(context.Background(), sigStates[i], sigR2P2P[i]) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + sigR3[i] = out.Messages[0] + } + + // Round 4 + sigR4 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound4(sigStates[i], sigR3) + if err != nil { + t.Fatalf("SignRound4[%d]: %v", i, err) + } + sigR4[i] = out.Messages[0] + } + + // Round 5 + sigR5 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound5(sigStates[i], sigR4) + if err != nil { + t.Fatalf("SignRound5[%d]: %v", i, err) + } + sigR5[i] = out.Messages[0] + } + + // Round 6 + sigR6 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound6(sigStates[i]) + if err != nil { + t.Fatalf("SignRound6[%d]: %v", i, err) + } + sigR6[i] = out.Messages[0] + } + + // Round 7 + sigR7 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound7(sigStates[i], sigR5, sigR6) + if err != nil { + t.Fatalf("SignRound7[%d]: %v", i, err) + } + sigR7[i] = out.Messages[0] + } + + // Round 8 + sigR8 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound8(sigStates[i]) + if err != nil { + t.Fatalf("SignRound8[%d]: %v", i, err) + } + sigR8[i] = out.Messages[0] + } + + // Round 9 + sigR9 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound9(sigStates[i], sigR7, sigR8) + if err != nil { + t.Fatalf("SignRound9[%d]: %v", i, err) + } + sigR9[i] = out.Messages[0] + } + + // Finalize + for i := 0; i < n; i++ { + out, err := SignFinalize(sigStates[i], sigR9) + if err != nil { + t.Fatalf("SignFinalize[%d]: %v", i, err) + } + if out.Signature == nil { + t.Fatalf("SignFinalize[%d]: no signature", i) + } + // Verify independently + pk := ecdsa.PublicKey{ + Curve: tss.S256(), + X: saves[0].ECDSAPub.X(), + Y: saves[0].ECDSAPub.Y(), + } + r := new(big.Int).SetBytes(out.Signature.R) + s := new(big.Int).SetBytes(out.Signature.S) + if !ecdsa.Verify(&pk, msgHash[:], r, s) { + t.Fatalf("party %d: signature verification failed", i) + } + t.Logf("party %d: signature verified (r=%x, s=%x)", i, + out.Signature.R, out.Signature.S) + } +} + +// TestRoundFnSignSubset does keygen(5) then signs with threshold+1=2 +// parties — exercising the auto-subset path where len(key.Ks) > +// signing committee size. +func TestRoundFnSignSubset(t *testing.T) { + const nKeygen = 5 + const nSign = 2 + const threshold = 1 // 2-of-5 + + // -- Keygen with 5 parties -- + preParams := testutil.LoadPreParams(t, nKeygen) + pIDs := tss.GenerateTestPartyIDs(nKeygen) + peerCtx := tss.NewPeerContext(pIDs) + + kgStates := make([]*keygen.KeygenState, nKeygen) + kgR1 := make([]*tss.Message, nKeygen) + for i := 0; i < nKeygen; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], nKeygen, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + + kgR2P2P := make([][]*tss.Message, nKeygen) + kgR2Bcast := make([]*tss.Message, nKeygen) + for i := 0; i < nKeygen; i++ { + kgR2P2P[i] = make([]*tss.Message, nKeygen) + } + for i := 0; i < nKeygen; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + + kgR3 := make([]*tss.Message, nKeygen) + for i := 0; i < nKeygen; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + + allKeys := make([]keygen.LocalPartySaveData, nKeygen) + for i := 0; i < nKeygen; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("keygen Round4[%d]: %v", i, err) + } + allKeys[i] = *out.Save + } + t.Logf("keygen(5) done: ECDSAPub = (%x...)", allKeys[0].ECDSAPub.X().Bytes()[:4]) + + // -- Sign with first 2 parties (subset of 5) -- + signPIDs := tss.SortPartyIDs( + tss.UnSortedPartyIDs{pIDs[0], pIDs[1]}) + signCtx := tss.NewPeerContext(signPIDs) + + msgHash := sha256.Sum256([]byte("subset signing test")) + m := new(big.Int).SetBytes(msgHash[:]) + + sigStates := make([]*SigningState, nSign) + sigR1P2P := make([][]*tss.Message, nSign) + sigR1Bcast := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + sigR1P2P[i] = make([]*tss.Message, nSign) + } + + // Find original key index for each signer + signerOrigIdx := make([]int, nSign) + for i, spid := range signPIDs { + for j, kpid := range pIDs { + if spid.KeyInt().Cmp(kpid.KeyInt()) == 0 { + signerOrigIdx[i] = j + break + } + } + } + + for i := 0; i < nSign; i++ { + params := tss.NewParameters(tss.S256(), signCtx, signPIDs[i], nSign, threshold) + // Pass FULL key data — SignRound1 should auto-subset + st, out, err := SignRound1(params, allKeys[signerOrigIdx[i]], m, nil, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + sigStates[i] = st + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + sigR1Bcast[i] = pm + } else { + for _, to := range pm.To { + sigR1P2P[to.Index][i] = pm + } + } + } + } + + // Rounds 2-9 + Finalize + sigR2P2P := make([][]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + sigR2P2P[i] = make([]*tss.Message, nSign) + } + for i := 0; i < nSign; i++ { + out, err := SignRound2(context.Background(), sigStates[i], sigR1P2P[i], sigR1Bcast) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + for _, to := range pm.To { + sigR2P2P[to.Index][i] = pm + } + } + } + + sigR3 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound3(context.Background(), sigStates[i], sigR2P2P[i]) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + sigR3[i] = out.Messages[0] + } + + sigR4 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound4(sigStates[i], sigR3) + if err != nil { + t.Fatalf("SignRound4[%d]: %v", i, err) + } + sigR4[i] = out.Messages[0] + } + + sigR5 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound5(sigStates[i], sigR4) + if err != nil { + t.Fatalf("SignRound5[%d]: %v", i, err) + } + sigR5[i] = out.Messages[0] + } + + sigR6 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound6(sigStates[i]) + if err != nil { + t.Fatalf("SignRound6[%d]: %v", i, err) + } + sigR6[i] = out.Messages[0] + } + + sigR7 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound7(sigStates[i], sigR5, sigR6) + if err != nil { + t.Fatalf("SignRound7[%d]: %v", i, err) + } + sigR7[i] = out.Messages[0] + } + + sigR8 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound8(sigStates[i]) + if err != nil { + t.Fatalf("SignRound8[%d]: %v", i, err) + } + sigR8[i] = out.Messages[0] + } + + sigR9 := make([]*tss.Message, nSign) + for i := 0; i < nSign; i++ { + out, err := SignRound9(sigStates[i], sigR7, sigR8) + if err != nil { + t.Fatalf("SignRound9[%d]: %v", i, err) + } + sigR9[i] = out.Messages[0] + } + + for i := 0; i < nSign; i++ { + out, err := SignFinalize(sigStates[i], sigR9) + if err != nil { + t.Fatalf("SignFinalize[%d]: %v", i, err) + } + pk := ecdsa.PublicKey{ + Curve: tss.S256(), + X: allKeys[0].ECDSAPub.X(), + Y: allKeys[0].ECDSAPub.Y(), + } + r := new(big.Int).SetBytes(out.Signature.R) + s := new(big.Int).SetBytes(out.Signature.S) + if !ecdsa.Verify(&pk, msgHash[:], r, s) { + t.Fatalf("party %d: subset signature verification failed", i) + } + } + t.Log("subset sign (2-of-5) verified") +} + +// TestRoundFnSignLeadingZeroMsg exercises signing where the hash +// has leading zero bytes (tests fullBytesLen padding path). +func TestRoundFnSignLeadingZeroMsg(t *testing.T) { + const n = 3 + const threshold = 1 + + preParams := testutil.LoadPreParams(t, n) + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + // Keygen + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, _ := keygen.Round2(context.Background(), kgStates[i], kgR1) + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, _ := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + kgR3[i] = out.Messages[0] + } + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, _ := keygen.Round4(context.Background(), kgStates[i], kgR3) + saves[i] = *out.Save + } + + // Sign with leading-zero message (first byte = 0x00) + msgData := []byte{ + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + } + m := new(big.Int).SetBytes(msgData) + + sigStates := make([]*SigningState, n) + sigR1P2P := make([][]*tss.Message, n) + sigR1Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + sigR1P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, threshold) + st, out, err := SignRound1(params, saves[i], m, nil, len(msgData)) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + sigStates[i] = st + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + sigR1Bcast[i] = pm + } else { + for _, to := range pm.To { + sigR1P2P[to.Index][i] = pm + } + } + } + } + + // Run rounds 2-9 + finalize (same boilerplate) + r2P2P := make([][]*tss.Message, n) + for i := 0; i < n; i++ { + r2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := SignRound2(context.Background(), sigStates[i], sigR1P2P[i], sigR1Bcast) + if err != nil { + t.Fatalf("R2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + for _, to := range pm.To { + r2P2P[to.Index][i] = pm + } + } + } + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound3(context.Background(), sigStates[i], r2P2P[i]) + if err != nil { + t.Fatalf("R3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + r4 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound4(sigStates[i], r3) + if err != nil { + t.Fatalf("R4[%d]: %v", i, err) + } + r4[i] = out.Messages[0] + } + r5 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound5(sigStates[i], r4) + if err != nil { + t.Fatalf("R5[%d]: %v", i, err) + } + r5[i] = out.Messages[0] + } + r6 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound6(sigStates[i]) + if err != nil { + t.Fatalf("R6[%d]: %v", i, err) + } + r6[i] = out.Messages[0] + } + r7 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound7(sigStates[i], r5, r6) + if err != nil { + t.Fatalf("R7[%d]: %v", i, err) + } + r7[i] = out.Messages[0] + } + r8 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound8(sigStates[i]) + if err != nil { + t.Fatalf("R8[%d]: %v", i, err) + } + r8[i] = out.Messages[0] + } + r9 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound9(sigStates[i], r7, r8) + if err != nil { + t.Fatalf("R9[%d]: %v", i, err) + } + r9[i] = out.Messages[0] + } + for i := 0; i < n; i++ { + out, err := SignFinalize(sigStates[i], r9) + if err != nil { + t.Fatalf("Finalize[%d]: %v", i, err) + } + // Verify M preserves leading zeros + if len(out.Signature.M) != len(msgData) { + t.Fatalf("party %d: M length %d != %d", i, len(out.Signature.M), len(msgData)) + } + if out.Signature.M[0] != 0x00 || out.Signature.M[1] != 0x00 { + t.Fatalf("party %d: leading zeros lost", i) + } + } + t.Log("sign with leading zero msg: passed") +} diff --git a/tss-lib/ecdsa/signing/round_state.go b/tss-lib/ecdsa/signing/round_state.go new file mode 100644 index 0000000..dc76cf7 --- /dev/null +++ b/tss-lib/ecdsa/signing/round_state.go @@ -0,0 +1,29 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// SigningState holds all mutable state between signing rounds. +// Opaque to the caller. +type SigningState struct { + params *tss.Parameters + key *keygen.LocalPartySaveData + data *SignatureData + temp *localTempData +} + +// SignRoundOutput holds the outbound messages and artifacts +// produced by a single signing round function. +type SignRoundOutput struct { + // Messages to send. Broadcast: GetTo() == nil. + Messages []*tss.Message + + // Signature is non-nil only after Finalize. + Signature *SignatureData +} diff --git a/tss-lib/ecdsa/signing/rounds.go b/tss-lib/ecdsa/signing/rounds.go deleted file mode 100644 index 2646c9f..0000000 --- a/tss-lib/ecdsa/signing/rounds.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/ecdsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - TaskName = "signing" -) - -type ( - base struct { - *tss.Parameters - key *keygen.LocalPartySaveData - data *common.SignatureData - temp *localTempData - out chan<- tss.Message - end chan<- *common.SignatureData - ok []bool // `ok` tracks parties which have been verified by Update() - started bool - number int - } - round1 struct { - *base - } - round2 struct { - *round1 - } - round3 struct { - *round2 - } - round4 struct { - *round3 - } - round5 struct { - *round4 - } - round6 struct { - *round5 - } - round7 struct { - *round6 - } - round8 struct { - *round7 - } - round9 struct { - *round8 - } - finalization struct { - *round9 - } -) - -var ( - _ tss.Round = (*round1)(nil) - _ tss.Round = (*round2)(nil) - _ tss.Round = (*round3)(nil) - _ tss.Round = (*round4)(nil) - _ tss.Round = (*round5)(nil) - _ tss.Round = (*round6)(nil) - _ tss.Round = (*round7)(nil) - _ tss.Round = (*round8)(nil) - _ tss.Round = (*round9)(nil) - _ tss.Round = (*finalization)(nil) -) - -// ----- // - -func (round *base) Params() *tss.Parameters { - return round.Parameters -} - -func (round *base) RoundNumber() int { - return round.number -} - -// CanProceed is inherited by other rounds -func (round *base) CanProceed() bool { - if !round.started { - return false - } - for _, ok := range round.ok { - if !ok { - return false - } - } - return true -} - -// WaitingFor is called by a Party for reporting back to the caller -func (round *base) WaitingFor() []*tss.PartyID { - Ps := round.Parties().IDs() - ids := make([]*tss.PartyID, 0, len(round.ok)) - for j, ok := range round.ok { - if ok { - continue - } - ids = append(ids, Ps[j]) - } - return ids -} - -func (round *base) WrapError(err error, culprits ...*tss.PartyID) *tss.Error { - return tss.NewError(err, TaskName, round.number, round.PartyID(), culprits...) -} - -// ----- // - -// `ok` tracks parties which have been verified by Update() -func (round *base) resetOK() { - for j := range round.ok { - round.ok[j] = false - } -} - -// get ssid from local params -func (round *base) getSSID() ([]byte, error) { - ssidList := []*big.Int{round.EC().Params().P, round.EC().Params().N, round.EC().Params().B, round.EC().Params().Gx, round.EC().Params().Gy} // ec curve - ssidList = append(ssidList, round.Parties().IDs().Keys()...) // parties - BigXjList, err := crypto.FlattenECPoints(round.key.BigXj) - if err != nil { - return nil, round.WrapError(errors.New("read BigXj failed"), round.PartyID()) - } - ssidList = append(ssidList, BigXjList...) // BigXj - ssidList = append(ssidList, round.key.NTildej...) // NTilde - ssidList = append(ssidList, round.key.H1j...) // h1 - ssidList = append(ssidList, round.key.H2j...) // h2 - ssidList = append(ssidList, big.NewInt(int64(round.number))) // round number - ssidList = append(ssidList, round.temp.ssidNonce) - ssid := common.SHA512_256i(ssidList...).Bytes() - - return ssid, nil -} diff --git a/tss-lib/ecdsa/signing/ssid_test.go b/tss-lib/ecdsa/signing/ssid_test.go new file mode 100644 index 0000000..2816920 --- /dev/null +++ b/tss-lib/ecdsa/signing/ssid_test.go @@ -0,0 +1,388 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "bytes" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// buildSigningSSIDFixture creates minimal but structurally valid inputs +// for getSigningSSID. Party keys are deterministic so tests are +// reproducible. +func buildSigningSSIDFixture(t *testing.T, n, threshold int) (params *tss.Parameters, key *keygen.LocalPartySaveData, temp *localTempData) { + t.Helper() + ec := tss.S256() + + ids := make(tss.UnSortedPartyIDs, n) + for i := 0; i < n; i++ { + ids[i] = tss.NewPartyID( + big.NewInt(int64(i)).String(), + "P", + big.NewInt(int64(100+i+1)), + ) + } + sorted := tss.SortPartyIDs(ids) + peerCtx := tss.NewPeerContext(sorted) + params = tss.NewParameters(ec, peerCtx, sorted[0], n, threshold) + + save := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + save.BigXj[i] = crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + save.NTildej[i] = big.NewInt(int64(1000 + i)) + save.H1j[i] = big.NewInt(int64(2000 + i)) + save.H2j[i] = big.NewInt(int64(3000 + i)) + } + + key = &save + temp = &localTempData{ + ssidNonce: big.NewInt(42), + m: new(big.Int).SetBytes([]byte("test-message-hash")), + } + return +} + +// ---------- Determinism ---------- + +func TestGetSigningSSIDDeterministic(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + ssid1, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("call 1: %v", err) + } + ssid2, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("call 2: %v", err) + } + if !bytes.Equal(ssid1, ssid2) { + t.Fatalf("not deterministic: %x != %x", ssid1, ssid2) + } + if len(ssid1) == 0 { + t.Fatal("returned empty SSID") + } +} + +// ---------- CeremonyID ---------- + +func TestGetSigningSSIDWithCeremonyID(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + ssidNone, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("no CID: %v", err) + } + + params.SetCeremonyID([]byte("ceremony-A")) + ssidA, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("CID-A: %v", err) + } + if bytes.Equal(ssidNone, ssidA) { + t.Fatal("CeremonyID did not change SSID") + } + + params.SetCeremonyID([]byte("ceremony-B")) + ssidB, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("CID-B: %v", err) + } + if bytes.Equal(ssidA, ssidB) { + t.Fatal("different CeremonyIDs produced same SSID") + } +} + +// ---------- Round number ---------- + +func TestGetSigningSSIDDifferentRoundNumbers(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + seen := make(map[string]int) + for round := 1; round <= 5; round++ { + ssid, err := getSigningSSID(params, key, temp, round) + if err != nil { + t.Fatalf("round %d: %v", round, err) + } + k := string(ssid) + if prev, ok := seen[k]; ok { + t.Fatalf("round %d collides with round %d", round, prev) + } + seen[k] = round + } +} + +// ---------- Nonce ---------- + +func TestGetSigningSSIDDifferentNonce(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + ssid1, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("nonce=42: %v", err) + } + + temp2 := &localTempData{ssidNonce: big.NewInt(99), m: temp.m} + ssid2, err := getSigningSSID(params, key, temp2, 1) + if err != nil { + t.Fatalf("nonce=99: %v", err) + } + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different nonces produced same SSID") + } +} + +// ---------- Message hash sensitivity (signing-specific) ---------- + +func TestGetSigningSSIDDifferentMessage(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + ssid1, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("msg-A: %v", err) + } + + temp2 := &localTempData{ + ssidNonce: temp.ssidNonce, + m: new(big.Int).SetBytes([]byte("different-message-hash")), + } + ssid2, err := getSigningSSID(params, key, temp2, 1) + if err != nil { + t.Fatalf("msg-B: %v", err) + } + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different message hashes must produce different SSIDs") + } +} + +func TestGetSigningSSIDNilMessageVsNonNil(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + ssidWithMsg, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("with m: %v", err) + } + + tempNil := &localTempData{ssidNonce: temp.ssidNonce, m: nil} + ssidNoMsg, err := getSigningSSID(params, key, tempNil, 1) + if err != nil { + t.Fatalf("nil m: %v", err) + } + if bytes.Equal(ssidWithMsg, ssidNoMsg) { + t.Fatal("nil m and non-nil m must produce different SSIDs") + } +} + +// ---------- BigXj sensitivity ---------- + +func TestGetSigningSSIDDifferentBigXj(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + + ssidOrig, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("original: %v", err) + } + + for i := 0; i < 3; i++ { + t.Run(big.NewInt(int64(i)).String(), func(t *testing.T) { + clone := cloneLocalPartySaveData(key, 3) + clone.BigXj[i] = crypto.ScalarBaseMult(tss.S256(), big.NewInt(999)) + ssid, err := getSigningSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated BigXj[%d]: %v", i, err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatalf("changing BigXj[%d] did not change SSID", i) + } + }) + } +} + +// ---------- NTildej / H1j / H2j sensitivity ---------- + +func TestGetSigningSSIDDifferentNTildej(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + ssidOrig, _ := getSigningSSID(params, key, temp, 1) + + clone := cloneLocalPartySaveData(key, 3) + clone.NTildej[1] = big.NewInt(99999) + ssid, err := getSigningSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated NTildej: %v", err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatal("changing NTildej did not change SSID") + } +} + +func TestGetSigningSSIDDifferentH1j(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + ssidOrig, _ := getSigningSSID(params, key, temp, 1) + + clone := cloneLocalPartySaveData(key, 3) + clone.H1j[1] = big.NewInt(99999) + ssid, err := getSigningSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated H1j: %v", err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatal("changing H1j did not change SSID") + } +} + +func TestGetSigningSSIDDifferentH2j(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + ssidOrig, _ := getSigningSSID(params, key, temp, 1) + + clone := cloneLocalPartySaveData(key, 3) + clone.H2j[1] = big.NewInt(99999) + ssid, err := getSigningSSID(params, clone, temp, 1) + if err != nil { + t.Fatalf("mutated H2j: %v", err) + } + if bytes.Equal(ssidOrig, ssid) { + t.Fatal("changing H2j did not change SSID") + } +} + +// ---------- Party keys, threshold, party count ---------- + +func TestGetSigningSSIDDifferentPartyKeys(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + ssidOrig, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("original: %v", err) + } + + // Rebuild params with a different key for party 1. + ids := tss.UnSortedPartyIDs{ + tss.NewPartyID("0", "P", big.NewInt(101)), + tss.NewPartyID("1", "P", big.NewInt(999)), // changed from 102 + tss.NewPartyID("2", "P", big.NewInt(103)), + } + sorted := tss.SortPartyIDs(ids) + peerCtx := tss.NewPeerContext(sorted) + params2 := tss.NewParameters(tss.S256(), peerCtx, sorted[0], 3, 1) + + ssid2, err := getSigningSSID(params2, key, temp, 1) + if err != nil { + t.Fatalf("changed key: %v", err) + } + if bytes.Equal(ssidOrig, ssid2) { + t.Fatal("different party keys must produce different SSIDs") + } +} + +func TestGetSigningSSIDDifferentThreshold(t *testing.T) { + ec := tss.S256() + ids := tss.UnSortedPartyIDs{ + tss.NewPartyID("0", "P", big.NewInt(101)), + tss.NewPartyID("1", "P", big.NewInt(102)), + tss.NewPartyID("2", "P", big.NewInt(103)), + tss.NewPartyID("3", "P", big.NewInt(104)), + } + sorted := tss.SortPartyIDs(ids) + peerCtx := tss.NewPeerContext(sorted) + + save := keygen.NewLocalPartySaveData(4) + for i := 0; i < 4; i++ { + save.BigXj[i] = crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + save.NTildej[i] = big.NewInt(int64(1000 + i)) + save.H1j[i] = big.NewInt(int64(2000 + i)) + save.H2j[i] = big.NewInt(int64(3000 + i)) + } + temp := &localTempData{ssidNonce: big.NewInt(0), m: big.NewInt(12345)} + + params1 := tss.NewParameters(ec, peerCtx, sorted[0], 4, 1) + ssid1, err := getSigningSSID(params1, &save, temp, 1) + if err != nil { + t.Fatalf("threshold=1: %v", err) + } + + params2 := tss.NewParameters(ec, peerCtx, sorted[0], 4, 2) + ssid2, err := getSigningSSID(params2, &save, temp, 1) + if err != nil { + t.Fatalf("threshold=2: %v", err) + } + + if bytes.Equal(ssid1, ssid2) { + t.Fatal("different thresholds must produce different SSIDs") + } +} + +func TestGetSigningSSIDDifferentPartyCount(t *testing.T) { + ec := tss.S256() + temp := &localTempData{ssidNonce: big.NewInt(0), m: big.NewInt(12345)} + + makeSave := func(n int) *keygen.LocalPartySaveData { + s := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + s.BigXj[i] = crypto.ScalarBaseMult(ec, big.NewInt(int64(i+7))) + s.NTildej[i] = big.NewInt(int64(1000 + i)) + s.H1j[i] = big.NewInt(int64(2000 + i)) + s.H2j[i] = big.NewInt(int64(3000 + i)) + } + return &s + } + + ids3 := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + tss.NewPartyID("0", "P", big.NewInt(101)), + tss.NewPartyID("1", "P", big.NewInt(102)), + tss.NewPartyID("2", "P", big.NewInt(103)), + }) + params3 := tss.NewParameters(ec, tss.NewPeerContext(ids3), ids3[0], 3, 1) + ssid3, err := getSigningSSID(params3, makeSave(3), temp, 1) + if err != nil { + t.Fatalf("n=3: %v", err) + } + + ids4 := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + tss.NewPartyID("0", "P", big.NewInt(101)), + tss.NewPartyID("1", "P", big.NewInt(102)), + tss.NewPartyID("2", "P", big.NewInt(103)), + tss.NewPartyID("3", "P", big.NewInt(104)), + }) + params4 := tss.NewParameters(ec, tss.NewPeerContext(ids4), ids4[0], 4, 1) + ssid4, err := getSigningSSID(params4, makeSave(4), temp, 1) + if err != nil { + t.Fatalf("n=4: %v", err) + } + + if bytes.Equal(ssid3, ssid4) { + t.Fatal("different party counts must produce different SSIDs") + } +} + +// ---------- Output length ---------- + +func TestGetSigningSSIDOutputLength(t *testing.T) { + params, key, temp := buildSigningSSIDFixture(t, 3, 1) + ssid, err := getSigningSSID(params, key, temp, 1) + if err != nil { + t.Fatalf("getSigningSSID: %v", err) + } + if len(ssid) == 0 || len(ssid) > 32 { + t.Fatalf("SSID length should be in (0, 32], got %d", len(ssid)) + } +} + +// ---------- helpers ---------- + +// cloneLocalPartySaveData creates a shallow clone of the save data with +// deep-copied slices so mutations don't affect the original. +func cloneLocalPartySaveData(src *keygen.LocalPartySaveData, n int) *keygen.LocalPartySaveData { + dst := keygen.NewLocalPartySaveData(n) + for i := 0; i < n; i++ { + dst.BigXj[i] = src.BigXj[i] // ECPoint is immutable + dst.NTildej[i] = new(big.Int).Set(src.NTildej[i]) + dst.H1j[i] = new(big.Int).Set(src.H1j[i]) + dst.H2j[i] = new(big.Int).Set(src.H2j[i]) + } + return &dst +} diff --git a/tss-lib/ecdsa/signing/test_helpers_test.go b/tss-lib/ecdsa/signing/test_helpers_test.go new file mode 100644 index 0000000..0acec61 --- /dev/null +++ b/tss-lib/ecdsa/signing/test_helpers_test.go @@ -0,0 +1,804 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "context" + "crypto/sha256" + "errors" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/testutil" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// requireCulprit unwraps a *tss.Error and asserts the culprit has the expected index. +func requireCulprit(t *testing.T, err error, wantIdx int) { + t.Helper() + tssErr := &tss.Error{} + if ok := errors.As(err, &tssErr); !ok { + t.Fatalf("expected *tss.Error, got %T", err) + } + culprits := tssErr.Culprits() + if len(culprits) != 1 || culprits[0].Index != wantIdx { + t.Fatalf("expected culprit index %d, got: %v", wantIdx, culprits) + } +} + +// testN is the fixed party count for negative test fixtures. +const testN = 3 + +// testThreshold is the fixed threshold for negative test fixtures (2-of-3). +const testThreshold = 1 + +// testMsg returns a deterministic message hash for signing test fixtures. +func testMsg() *big.Int { + h := sha256.Sum256([]byte("negative test fixture message")) + return new(big.Int).SetBytes(h[:]) +} + +// doKeygen runs a full 3-party keygen ceremony (with proofs enabled) +// and returns the save data for each party. +func doKeygen(t *testing.T) []keygen.LocalPartySaveData { + t.Helper() + const n = testN + + preParams := testutil.LoadPreParams(t, n) + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + kgStates := make([]*keygen.KeygenState, n) + kgR1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, testThreshold) + st, out, err := keygen.Round1(context.Background(), params, preParams[i]) + if err != nil { + t.Fatalf("doKeygen: Round1[%d]: %v", i, err) + } + kgStates[i] = st + kgR1[i] = out.Messages[0] + } + + kgR2P2P := make([][]*tss.Message, n) + kgR2Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + kgR2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(context.Background(), kgStates[i], kgR1) + if err != nil { + t.Fatalf("doKeygen: Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + kgR2Bcast[i] = pm + } else { + for _, to := range pm.To { + kgR2P2P[to.Index][i] = pm + } + } + } + kgR2P2P[i][i] = kgStates[i].ExportR2P2PSelf() + if kgR2Bcast[i] == nil { + kgR2Bcast[i] = kgStates[i].ExportR2BcastSelf() + } + } + + kgR3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(context.Background(), kgStates[i], kgR2P2P[i], kgR2Bcast) + if err != nil { + t.Fatalf("doKeygen: Round3[%d]: %v", i, err) + } + kgR3[i] = out.Messages[0] + } + + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round4(context.Background(), kgStates[i], kgR3) + if err != nil { + t.Fatalf("doKeygen: Round4[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves +} + +// setupPartyIDs returns a consistent set of party IDs and peer context +// for the test fixture party count. +func setupPartyIDs() (tss.SortedPartyIDs, *tss.PeerContext) { + pIDs := tss.GenerateTestPartyIDs(testN) + return pIDs, tss.NewPeerContext(pIDs) +} + +// ----------------------------------------------------------------- +// Round fixture types +// ----------------------------------------------------------------- + +// SignFixture holds the accumulated state from running signing rounds. +// Each setupThroughRoundN function returns this with progressively +// more fields populated. +type SignFixture struct { + // Party infrastructure + PIDs tss.SortedPartyIDs + PeerCtx *tss.PeerContext + Keys []keygen.LocalPartySaveData + Msg *big.Int + + // Per-party signing state (mutated as rounds progress) + States []*SigningState + + // Round 1 outputs + R1P2P [][]*tss.Message // R1P2P[recipient][sender] + R1Bcast []*tss.Message // R1Bcast[sender] + + // Round 2 outputs + R2P2P [][]*tss.Message // R2P2P[recipient][sender] + + // Round 3 outputs + R3Bcast []*tss.Message // R3Bcast[sender] + + // Round 4 outputs + R4Bcast []*tss.Message // R4Bcast[sender] + + // Round 5 outputs + R5Bcast []*tss.Message // R5Bcast[sender] + + // Round 6 outputs + R6Bcast []*tss.Message // R6Bcast[sender] + + // Round 7 outputs + R7Bcast []*tss.Message // R7Bcast[sender] + + // Round 8 outputs + R8Bcast []*tss.Message // R8Bcast[sender] + + // Round 9 outputs + R9Bcast []*tss.Message // R9Bcast[sender] +} + +// ----------------------------------------------------------------- +// setupSignRound1 +// ----------------------------------------------------------------- + +// setupSignRound1 runs keygen and SignRound1 for all parties. +// Returns the fixture with States, R1P2P, and R1Bcast populated. +func setupSignRound1(t *testing.T, keys []keygen.LocalPartySaveData) *SignFixture { + t.Helper() + const n = testN + + pIDs, peerCtx := setupPartyIDs() + m := testMsg() + + states := make([]*SigningState, n) + r1P2P := make([][]*tss.Message, n) + r1Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + r1P2P[i] = make([]*tss.Message, n) + } + + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.S256(), peerCtx, pIDs[i], n, testThreshold) + st, out, err := SignRound1(params, keys[i], m, nil, 0) + if err != nil { + t.Fatalf("setupSignRound1: SignRound1[%d]: %v", i, err) + } + states[i] = st + for _, msg := range out.Messages { + pm := msg + if pm.To == nil { + r1Bcast[i] = pm + } else { + for _, to := range pm.To { + r1P2P[to.Index][i] = pm + } + } + } + } + + return &SignFixture{ + PIDs: pIDs, + PeerCtx: peerCtx, + Keys: keys, + Msg: m, + States: states, + R1P2P: r1P2P, + R1Bcast: r1Bcast, + } +} + +// ----------------------------------------------------------------- +// setupThroughRound2 +// ----------------------------------------------------------------- + +// setupThroughRound2 runs keygen + rounds 1-2. Returns fixture with +// R2P2P populated (P2P messages). +func setupThroughRound2(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + keys := doKeygen(t) + f := setupSignRound1(t, keys) + + r2P2P := make([][]*tss.Message, n) + for i := 0; i < n; i++ { + r2P2P[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := SignRound2(context.Background(), f.States[i], f.R1P2P[i], f.R1Bcast) + if err != nil { + t.Fatalf("setupThroughRound2: SignRound2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + pm := msg + for _, to := range pm.To { + r2P2P[to.Index][i] = pm + } + } + } + + f.R2P2P = r2P2P + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound3 +// ----------------------------------------------------------------- + +// setupThroughRound3 runs keygen + rounds 1-3. Returns fixture with +// R3Bcast populated (broadcast theta shares). +func setupThroughRound3(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound2(t) + + r3Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound3(context.Background(), f.States[i], f.R2P2P[i]) + if err != nil { + t.Fatalf("setupThroughRound3: SignRound3[%d]: %v", i, err) + } + r3Bcast[i] = out.Messages[0] + } + + f.R3Bcast = r3Bcast + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound4 +// ----------------------------------------------------------------- + +// setupThroughRound4 runs keygen + rounds 1-4. Returns fixture with +// R4Bcast populated (broadcast decommitment + ZK proof). +func setupThroughRound4(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound3(t) + + r4Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound4(f.States[i], f.R3Bcast) + if err != nil { + t.Fatalf("setupThroughRound4: SignRound4[%d]: %v", i, err) + } + r4Bcast[i] = out.Messages[0] + } + + f.R4Bcast = r4Bcast + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound5 +// ----------------------------------------------------------------- + +// setupThroughRound5 runs keygen + rounds 1-5. Returns fixture with +// R5Bcast populated (broadcast commitment to blinding). +func setupThroughRound5(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound4(t) + + r5Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound5(f.States[i], f.R4Bcast) + if err != nil { + t.Fatalf("setupThroughRound5: SignRound5[%d]: %v", i, err) + } + r5Bcast[i] = out.Messages[0] + } + + f.R5Bcast = r5Bcast + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound6 +// ----------------------------------------------------------------- + +// setupThroughRound6 runs keygen + rounds 1-6. Returns fixture with +// R6Bcast populated (broadcast decommitment + Schnorr proofs). +func setupThroughRound6(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound5(t) + + r6Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound6(f.States[i]) + if err != nil { + t.Fatalf("setupThroughRound6: SignRound6[%d]: %v", i, err) + } + r6Bcast[i] = out.Messages[0] + } + + f.R6Bcast = r6Bcast + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound7 +// ----------------------------------------------------------------- + +// setupThroughRound7 runs keygen + rounds 1-7. Returns fixture with +// R7Bcast populated (broadcast commitment to Ui/Ti). +func setupThroughRound7(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound6(t) + + r7Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound7(f.States[i], f.R5Bcast, f.R6Bcast) + if err != nil { + t.Fatalf("setupThroughRound7: SignRound7[%d]: %v", i, err) + } + r7Bcast[i] = out.Messages[0] + } + + f.R7Bcast = r7Bcast + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound8 +// ----------------------------------------------------------------- + +// setupThroughRound8 runs keygen + rounds 1-8. Returns fixture with +// R8Bcast populated (broadcast decommitment of Ui/Ti). +func setupThroughRound8(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound7(t) + + r8Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound8(f.States[i]) + if err != nil { + t.Fatalf("setupThroughRound8: SignRound8[%d]: %v", i, err) + } + r8Bcast[i] = out.Messages[0] + } + + f.R8Bcast = r8Bcast + return f +} + +// ----------------------------------------------------------------- +// setupThroughRound9 +// ----------------------------------------------------------------- + +// setupThroughRound9 runs keygen + rounds 1-9. Returns fixture with +// R9Bcast populated (broadcast partial signature shares). +func setupThroughRound9(t *testing.T) *SignFixture { + t.Helper() + const n = testN + + f := setupThroughRound8(t) + + r9Bcast := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound9(f.States[i], f.R7Bcast, f.R8Bcast) + if err != nil { + t.Fatalf("setupThroughRound9: SignRound9[%d]: %v", i, err) + } + r9Bcast[i] = out.Messages[0] + } + + f.R9Bcast = r9Bcast + return f +} + +// ================================================================= +// Message cloning helpers +// ================================================================= +// +// Each clone function performs a deep copy of the message content so +// that negative tests can corrupt individual fields without affecting +// the original fixture data used by other parties. + +// cloneBigInt returns a deep copy of a *big.Int (nil-safe). +func cloneBigInt(v *big.Int) *big.Int { + if v == nil { + return nil + } + return new(big.Int).Set(v) +} + +// cloneBigInts returns a deep copy of a []*big.Int slice. +func cloneBigInts(vs []*big.Int) []*big.Int { + if vs == nil { + return nil + } + out := make([]*big.Int, len(vs)) + for i, v := range vs { + out[i] = cloneBigInt(v) + } + return out +} + +// cloneBytes returns a deep copy of a byte slice (nil-safe). +func cloneBytes(b []byte) []byte { + if b == nil { + return nil + } + out := make([]byte, len(b)) + copy(out, b) + return out +} + +// cloneMessage creates a shallow copy of a *tss.Message with the +// Content replaced by a deep-cloned version using the provided +// content cloner. The From and To pointers are shared (they are +// immutable party IDs). +func cloneMessage(m *tss.Message, clonedContent interface{}) *tss.Message { + return &tss.Message{ + From: m.From, + To: m.To, + IsBroadcast: m.IsBroadcast, + IsToOldCommittee: m.IsToOldCommittee, + IsToOldAndNewCommittees: m.IsToOldAndNewCommittees, + Content: clonedContent, + } +} + +// ----------------------------------------------------------------- +// Round 1 Message 1 (P2P): Paillier ciphertext + range proof +// ----------------------------------------------------------------- + +// cloneRangeProofAlice deep-copies a *mta.RangeProofAlice. +func cloneRangeProofAlice(p *mta.RangeProofAlice) *mta.RangeProofAlice { + if p == nil { + return nil + } + return &mta.RangeProofAlice{ + Z: cloneBigInt(p.Z), + U: cloneBigInt(p.U), + W: cloneBigInt(p.W), + S: cloneBigInt(p.S), + S1: cloneBigInt(p.S1), + S2: cloneBigInt(p.S2), + } +} + +// CloneSignRound1Message1 deep-copies a SignRound1Message1 content. +func CloneSignRound1Message1(m *SignRound1Message1) *SignRound1Message1 { + if m == nil { + return nil + } + return &SignRound1Message1{ + C: cloneBigInt(m.C), + RangeProofAlice: cloneRangeProofAlice(m.RangeProofAlice), + ReceiverID: cloneBytes(m.ReceiverID), + } +} + +// CloneR1P2PMsg deep-copies a Round 1 P2P message (SignRound1Message1). +func CloneR1P2PMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound1Message1(m.Content.(*SignRound1Message1))) +} + +// ----------------------------------------------------------------- +// Round 1 Message 2 (Broadcast): commitment +// ----------------------------------------------------------------- + +// CloneSignRound1Message2 deep-copies a SignRound1Message2 content. +func CloneSignRound1Message2(m *SignRound1Message2) *SignRound1Message2 { + if m == nil { + return nil + } + return &SignRound1Message2{ + Commitment: cloneBigInt(m.Commitment), + } +} + +// CloneR1BcastMsg deep-copies a Round 1 broadcast message (SignRound1Message2). +func CloneR1BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound1Message2(m.Content.(*SignRound1Message2))) +} + +// ----------------------------------------------------------------- +// Round 2 Message (P2P): MtA ciphertexts + Bob proofs +// ----------------------------------------------------------------- + +// cloneProofBob deep-copies a *mta.ProofBob. +func cloneProofBob(p *mta.ProofBob) *mta.ProofBob { + if p == nil { + return nil + } + return &mta.ProofBob{ + Z: cloneBigInt(p.Z), + ZPrm: cloneBigInt(p.ZPrm), + T: cloneBigInt(p.T), + V: cloneBigInt(p.V), + W: cloneBigInt(p.W), + S: cloneBigInt(p.S), + S1: cloneBigInt(p.S1), + S2: cloneBigInt(p.S2), + T1: cloneBigInt(p.T1), + T2: cloneBigInt(p.T2), + } +} + +// cloneProofBobWC deep-copies a *mta.ProofBobWC. +func cloneProofBobWC(p *mta.ProofBobWC) *mta.ProofBobWC { + if p == nil { + return nil + } + var u *crypto.ECPoint + if p.U != nil { + // ECPoint.X() and .Y() return copies already + u, _ = crypto.NewECPoint(p.U.Curve(), p.U.X(), p.U.Y()) + } + return &mta.ProofBobWC{ + ProofBob: cloneProofBob(p.ProofBob), + U: u, + } +} + +// CloneSignRound2Message deep-copies a SignRound2Message content. +func CloneSignRound2Message(m *SignRound2Message) *SignRound2Message { + if m == nil { + return nil + } + return &SignRound2Message{ + C1: cloneBigInt(m.C1), + C2: cloneBigInt(m.C2), + ProofBob: cloneProofBob(m.ProofBob), + ProofBobWC: cloneProofBobWC(m.ProofBobWC), + ReceiverID: cloneBytes(m.ReceiverID), + } +} + +// CloneR2P2PMsg deep-copies a Round 2 P2P message (SignRound2Message). +func CloneR2P2PMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound2Message(m.Content.(*SignRound2Message))) +} + +// ----------------------------------------------------------------- +// Round 3 Message (Broadcast): theta share +// ----------------------------------------------------------------- + +// CloneSignRound3Message deep-copies a SignRound3Message content. +func CloneSignRound3Message(m *SignRound3Message) *SignRound3Message { + if m == nil { + return nil + } + return &SignRound3Message{ + Theta: cloneBigInt(m.Theta), + } +} + +// CloneR3BcastMsg deep-copies a Round 3 broadcast message (SignRound3Message). +func CloneR3BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound3Message(m.Content.(*SignRound3Message))) +} + +// ----------------------------------------------------------------- +// Round 4 Message (Broadcast): decommitment + ZK proof +// ----------------------------------------------------------------- + +// cloneZKProof deep-copies a *schnorr.ZKProof. +func cloneZKProof(p *schnorr.ZKProof) *schnorr.ZKProof { + if p == nil { + return nil + } + var alpha *crypto.ECPoint + if p.Alpha != nil { + alpha, _ = crypto.NewECPoint(p.Alpha.Curve(), p.Alpha.X(), p.Alpha.Y()) + } + return &schnorr.ZKProof{ + Alpha: alpha, + T: cloneBigInt(p.T), + } +} + +// cloneDeCommitment deep-copies a commitments.HashDeCommitment ([]*big.Int). +func cloneDeCommitment(d commitments.HashDeCommitment) commitments.HashDeCommitment { + return cloneBigInts(d) +} + +// CloneSignRound4Message deep-copies a SignRound4Message content. +func CloneSignRound4Message(m *SignRound4Message) *SignRound4Message { + if m == nil { + return nil + } + return &SignRound4Message{ + DeCommitment: cloneDeCommitment(m.DeCommitment), + ZKProof: cloneZKProof(m.ZKProof), + } +} + +// CloneR4BcastMsg deep-copies a Round 4 broadcast message (SignRound4Message). +func CloneR4BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound4Message(m.Content.(*SignRound4Message))) +} + +// ----------------------------------------------------------------- +// Round 5 Message (Broadcast): commitment to blinding +// ----------------------------------------------------------------- + +// CloneSignRound5Message deep-copies a SignRound5Message content. +func CloneSignRound5Message(m *SignRound5Message) *SignRound5Message { + if m == nil { + return nil + } + return &SignRound5Message{ + Commitment: cloneBigInt(m.Commitment), + } +} + +// CloneR5BcastMsg deep-copies a Round 5 broadcast message (SignRound5Message). +func CloneR5BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound5Message(m.Content.(*SignRound5Message))) +} + +// ----------------------------------------------------------------- +// Round 6 Message (Broadcast): decommitment + ZK + ZKV proofs +// ----------------------------------------------------------------- + +// cloneZKVProof deep-copies a *schnorr.ZKVProof. +func cloneZKVProof(p *schnorr.ZKVProof) *schnorr.ZKVProof { + if p == nil { + return nil + } + var alpha *crypto.ECPoint + if p.Alpha != nil { + alpha, _ = crypto.NewECPoint(p.Alpha.Curve(), p.Alpha.X(), p.Alpha.Y()) + } + return &schnorr.ZKVProof{ + Alpha: alpha, + T: cloneBigInt(p.T), + U: cloneBigInt(p.U), + } +} + +// CloneSignRound6Message deep-copies a SignRound6Message content. +func CloneSignRound6Message(m *SignRound6Message) *SignRound6Message { + if m == nil { + return nil + } + return &SignRound6Message{ + DeCommitment: cloneDeCommitment(m.DeCommitment), + ZKProof: cloneZKProof(m.ZKProof), + ZKVProof: cloneZKVProof(m.ZKVProof), + } +} + +// CloneR6BcastMsg deep-copies a Round 6 broadcast message (SignRound6Message). +func CloneR6BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound6Message(m.Content.(*SignRound6Message))) +} + +// ----------------------------------------------------------------- +// Round 7 Message (Broadcast): commitment to Ui/Ti +// ----------------------------------------------------------------- + +// CloneSignRound7Message deep-copies a SignRound7Message content. +func CloneSignRound7Message(m *SignRound7Message) *SignRound7Message { + if m == nil { + return nil + } + return &SignRound7Message{ + Commitment: cloneBigInt(m.Commitment), + } +} + +// CloneR7BcastMsg deep-copies a Round 7 broadcast message (SignRound7Message). +func CloneR7BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound7Message(m.Content.(*SignRound7Message))) +} + +// ----------------------------------------------------------------- +// Round 8 Message (Broadcast): decommitment of Ui/Ti +// ----------------------------------------------------------------- + +// CloneSignRound8Message deep-copies a SignRound8Message content. +func CloneSignRound8Message(m *SignRound8Message) *SignRound8Message { + if m == nil { + return nil + } + return &SignRound8Message{ + DeCommitment: cloneDeCommitment(m.DeCommitment), + } +} + +// CloneR8BcastMsg deep-copies a Round 8 broadcast message (SignRound8Message). +func CloneR8BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound8Message(m.Content.(*SignRound8Message))) +} + +// ----------------------------------------------------------------- +// Round 9 Message (Broadcast): partial signature share +// ----------------------------------------------------------------- + +// CloneSignRound9Message deep-copies a SignRound9Message content. +func CloneSignRound9Message(m *SignRound9Message) *SignRound9Message { + if m == nil { + return nil + } + return &SignRound9Message{ + S: cloneBigInt(m.S), + } +} + +// CloneR9BcastMsg deep-copies a Round 9 broadcast message (SignRound9Message). +func CloneR9BcastMsg(m *tss.Message) *tss.Message { + return cloneMessage(m, CloneSignRound9Message(m.Content.(*SignRound9Message))) +} + +// ----------------------------------------------------------------- +// Broadcast/P2P slice cloning helpers +// ----------------------------------------------------------------- + +// CloneBcastSlice deep-copies a broadcast message slice using the +// provided per-message cloner. +func CloneBcastSlice(msgs []*tss.Message, cloner func(*tss.Message) *tss.Message) []*tss.Message { + if msgs == nil { + return nil + } + out := make([]*tss.Message, len(msgs)) + for i, m := range msgs { + if m != nil { + out[i] = cloner(m) + } + } + return out +} + +// CloneP2PSlice deep-copies a P2P message matrix (indexed as +// [recipient][sender]) using the provided per-message cloner. +func CloneP2PSlice(msgs [][]*tss.Message, cloner func(*tss.Message) *tss.Message) [][]*tss.Message { + if msgs == nil { + return nil + } + out := make([][]*tss.Message, len(msgs)) + for i, row := range msgs { + if row != nil { + out[i] = make([]*tss.Message, len(row)) + for j, m := range row { + if m != nil { + out[i][j] = cloner(m) + } + } + } + } + return out +} diff --git a/tss-lib/ecdsa/signing/types.go b/tss-lib/ecdsa/signing/types.go new file mode 100644 index 0000000..7671d57 --- /dev/null +++ b/tss-lib/ecdsa/signing/types.go @@ -0,0 +1,89 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TaskName identifies the signing protocol in error messages. +const TaskName = "signing" + +type ( + localMessageStore struct { + signRound1Message1s, + signRound1Message2s, + signRound2Messages, + signRound3Messages, + signRound4Messages, + signRound5Messages, + signRound6Messages, + signRound7Messages, + signRound8Messages, + signRound9Messages []*tss.Message + } + + localTempData struct { + localMessageStore + + // temp data (thrown away after sign) / round 1 + w, + m, + k, + theta, + thetaInverse, + sigma, + keyDerivationDelta, + gamma *big.Int + fullBytesLen int + cis []*big.Int + bigWs []*crypto.ECPoint + pointGamma *crypto.ECPoint + deCommit cmt.HashDeCommitment + + // round 2 + betas, // return value of Bob_mid + c1jis, + c2jis, + vs []*big.Int // return value of Bob_mid_wc + pi1jis []*mta.ProofBob + pi2jis []*mta.ProofBobWC + + // round 5 + li, + si, + rx, + ry, + roi *big.Int + bigR, + bigAi, + bigVi *crypto.ECPoint + DPower cmt.HashDeCommitment + + // round 7 + Ui, + Ti *crypto.ECPoint + DTelda cmt.HashDeCommitment + + ssidNonce *big.Int + ssid []byte + } +) + +func padToLengthBytesInPlace(src []byte, length int) []byte { + oriLen := len(src) + if oriLen < length { + for i := 0; i < length-oriLen; i++ { + src = append([]byte{0}, src...) + } + } + return src +} diff --git a/tss-lib/ecdsa/signing/validate_basic_test.go b/tss-lib/ecdsa/signing/validate_basic_test.go new file mode 100644 index 0000000..9f31ade --- /dev/null +++ b/tss-lib/ecdsa/signing/validate_basic_test.go @@ -0,0 +1,421 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + "testing" + + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/mta" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" +) + +// validR1M1 returns a SignRound1Message1 that passes ValidateBasic. +func validR1M1() *SignRound1Message1 { + return &SignRound1Message1{ + C: big.NewInt(42), + RangeProofAlice: &mta.RangeProofAlice{}, + ReceiverID: []byte("receiver"), + } +} + +func TestSignRound1Message1_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound1Message1 + want bool + }{ + {"valid", validR1M1(), true}, + {"nil receiver", nil, false}, + {"C nil", func() *SignRound1Message1 { + m := validR1M1() + m.C = nil + return m + }(), false}, + {"C zero", func() *SignRound1Message1 { + m := validR1M1() + m.C = big.NewInt(0) + return m + }(), false}, + {"C negative", func() *SignRound1Message1 { + m := validR1M1() + m.C = big.NewInt(-1) + return m + }(), false}, + {"RangeProofAlice nil", func() *SignRound1Message1 { + m := validR1M1() + m.RangeProofAlice = nil + return m + }(), false}, + {"ReceiverID nil", func() *SignRound1Message1 { + m := validR1M1() + m.ReceiverID = nil + return m + }(), false}, + {"ReceiverID empty", func() *SignRound1Message1 { + m := validR1M1() + m.ReceiverID = []byte{} + return m + }(), false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR1M2 returns a SignRound1Message2 that passes ValidateBasic. +func validR1M2() *SignRound1Message2 { + return &SignRound1Message2{Commitment: big.NewInt(99)} +} + +func TestSignRound1Message2_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound1Message2 + want bool + }{ + {"valid", validR1M2(), true}, + {"nil receiver", nil, false}, + {"Commitment nil", &SignRound1Message2{Commitment: nil}, false}, + {"Commitment zero", &SignRound1Message2{Commitment: big.NewInt(0)}, false}, + {"Commitment negative", &SignRound1Message2{Commitment: big.NewInt(-5)}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR2 returns a SignRound2Message that passes ValidateBasic. +func validR2() *SignRound2Message { + return &SignRound2Message{ + C1: big.NewInt(10), + C2: big.NewInt(20), + ProofBob: &mta.ProofBob{}, + ProofBobWC: &mta.ProofBobWC{}, + ReceiverID: []byte("recv"), + } +} + +func TestSignRound2Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound2Message + want bool + }{ + {"valid", validR2(), true}, + {"nil receiver", nil, false}, + {"C1 nil", func() *SignRound2Message { + m := validR2() + m.C1 = nil + return m + }(), false}, + {"C1 zero", func() *SignRound2Message { + m := validR2() + m.C1 = big.NewInt(0) + return m + }(), false}, + {"C1 negative", func() *SignRound2Message { + m := validR2() + m.C1 = big.NewInt(-3) + return m + }(), false}, + {"C2 nil", func() *SignRound2Message { + m := validR2() + m.C2 = nil + return m + }(), false}, + {"C2 zero", func() *SignRound2Message { + m := validR2() + m.C2 = big.NewInt(0) + return m + }(), false}, + {"C2 negative", func() *SignRound2Message { + m := validR2() + m.C2 = big.NewInt(-7) + return m + }(), false}, + {"ProofBob nil", func() *SignRound2Message { + m := validR2() + m.ProofBob = nil + return m + }(), false}, + {"ProofBobWC nil", func() *SignRound2Message { + m := validR2() + m.ProofBobWC = nil + return m + }(), false}, + {"ReceiverID nil", func() *SignRound2Message { + m := validR2() + m.ReceiverID = nil + return m + }(), false}, + {"ReceiverID empty", func() *SignRound2Message { + m := validR2() + m.ReceiverID = []byte{} + return m + }(), false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR3 returns a SignRound3Message that passes ValidateBasic. +func validR3() *SignRound3Message { + return &SignRound3Message{Theta: big.NewInt(77)} +} + +func TestSignRound3Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound3Message + want bool + }{ + {"valid", validR3(), true}, + {"nil receiver", nil, false}, + {"Theta nil", &SignRound3Message{Theta: nil}, false}, + {"Theta zero", &SignRound3Message{Theta: big.NewInt(0)}, false}, + {"Theta negative", &SignRound3Message{Theta: big.NewInt(-1)}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR4 returns a SignRound4Message that passes ValidateBasic. +func validR4() *SignRound4Message { + return &SignRound4Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: &schnorr.ZKProof{}, + } +} + +func TestSignRound4Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound4Message + want bool + }{ + {"valid with 2 elements", validR4(), true}, + {"valid with 3 elements", &SignRound4Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, + ZKProof: &schnorr.ZKProof{}, + }, true}, + {"nil receiver", nil, false}, + {"DeCommitment nil", &SignRound4Message{ + DeCommitment: nil, + ZKProof: &schnorr.ZKProof{}, + }, false}, + {"DeCommitment empty", &SignRound4Message{ + DeCommitment: cmt.HashDeCommitment{}, + ZKProof: &schnorr.ZKProof{}, + }, false}, + {"DeCommitment 1 element (boundary)", &SignRound4Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1)}, + ZKProof: &schnorr.ZKProof{}, + }, false}, + {"ZKProof nil", &SignRound4Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: nil, + }, false}, + {"both nil", &SignRound4Message{}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR5 returns a SignRound5Message that passes ValidateBasic. +func validR5() *SignRound5Message { + return &SignRound5Message{Commitment: big.NewInt(55)} +} + +func TestSignRound5Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound5Message + want bool + }{ + {"valid", validR5(), true}, + {"nil receiver", nil, false}, + {"Commitment nil", &SignRound5Message{Commitment: nil}, false}, + {"Commitment zero", &SignRound5Message{Commitment: big.NewInt(0)}, false}, + {"Commitment negative", &SignRound5Message{Commitment: big.NewInt(-1)}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR6 returns a SignRound6Message that passes ValidateBasic. +func validR6() *SignRound6Message { + return &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: &schnorr.ZKProof{}, + ZKVProof: &schnorr.ZKVProof{}, + } +} + +func TestSignRound6Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound6Message + want bool + }{ + {"valid with 2 elements", validR6(), true}, + {"valid with 3 elements", &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, + ZKProof: &schnorr.ZKProof{}, + ZKVProof: &schnorr.ZKVProof{}, + }, true}, + {"nil receiver", nil, false}, + {"DeCommitment nil", &SignRound6Message{ + DeCommitment: nil, + ZKProof: &schnorr.ZKProof{}, + ZKVProof: &schnorr.ZKVProof{}, + }, false}, + {"DeCommitment empty", &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{}, + ZKProof: &schnorr.ZKProof{}, + ZKVProof: &schnorr.ZKVProof{}, + }, false}, + {"DeCommitment 1 element (boundary)", &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1)}, + ZKProof: &schnorr.ZKProof{}, + ZKVProof: &schnorr.ZKVProof{}, + }, false}, + {"ZKProof nil", &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: nil, + ZKVProof: &schnorr.ZKVProof{}, + }, false}, + {"ZKVProof nil", &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: &schnorr.ZKProof{}, + ZKVProof: nil, + }, false}, + {"all fields zero-value", &SignRound6Message{}, false}, + {"only DeCommitment valid", &SignRound6Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + }, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR7 returns a SignRound7Message that passes ValidateBasic. +func validR7() *SignRound7Message { + return &SignRound7Message{Commitment: big.NewInt(88)} +} + +func TestSignRound7Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound7Message + want bool + }{ + {"valid", validR7(), true}, + {"nil receiver", nil, false}, + {"Commitment nil", &SignRound7Message{Commitment: nil}, false}, + {"Commitment zero", &SignRound7Message{Commitment: big.NewInt(0)}, false}, + {"Commitment negative", &SignRound7Message{Commitment: big.NewInt(-1)}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR8 returns a SignRound8Message that passes ValidateBasic. +func validR8() *SignRound8Message { + return &SignRound8Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + } +} + +func TestSignRound8Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound8Message + want bool + }{ + {"valid with 2 elements", validR8(), true}, + {"valid with 3 elements", &SignRound8Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, + }, true}, + {"nil receiver", nil, false}, + {"DeCommitment nil", &SignRound8Message{DeCommitment: nil}, false}, + {"DeCommitment empty", &SignRound8Message{DeCommitment: cmt.HashDeCommitment{}}, false}, + {"DeCommitment 1 element (boundary)", &SignRound8Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1)}, + }, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} + +// validR9 returns a SignRound9Message that passes ValidateBasic. +func validR9() *SignRound9Message { + return &SignRound9Message{S: big.NewInt(33)} +} + +func TestSignRound9Message_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *SignRound9Message + want bool + }{ + {"valid", validR9(), true}, + {"nil receiver", nil, false}, + {"S nil", &SignRound9Message{S: nil}, false}, + {"S zero", &SignRound9Message{S: big.NewInt(0)}, false}, + {"S negative", &SignRound9Message{S: big.NewInt(-1)}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.msg.ValidateBasic(); got != tt.want { + t.Errorf("ValidateBasic() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/tss-lib/eddsa/example_test.go b/tss-lib/eddsa/example_test.go new file mode 100644 index 0000000..af287a4 --- /dev/null +++ b/tss-lib/eddsa/example_test.go @@ -0,0 +1,343 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +//go:build tssexamples +// +build tssexamples + +// Package eddsa_test contains the canonical usage examples for the +// tss-lib v3 EdDSA round function API. +// +// Run with: go test -tags tssexamples -v ./eddsa/ -timeout 5m +package eddsa_test + +import ( + "crypto/sha256" + "fmt" + "math/big" + "testing" + + "github.com/decred/dcrd/dcrec/edwards/v2" + + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/eddsa/resharing" + "github.com/hemilabs/x/tss-lib/v3/eddsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestEdDSAKeygenSignReshare demonstrates the full lifecycle: +// keygen → sign → reshare (with overlapping committees) → sign again. +// +// Old committee: [P0, P1, P2], threshold=1 (2-of-3) +// New committee: [P1, P2, P3], threshold=1 (2-of-3) +// P1 and P2 are in both committees (overlap). +// P0 drops out, P3 joins. +// The EdDSA public key is preserved across the reshare. +func TestEdDSAKeygenSignReshare(t *testing.T) { + const threshold = 1 + + // ------------------------------------------------------------------ + // Step 1: Create 4 party IDs — 3 old, 1 new joiner. + // P1 and P2 overlap between old and new. + // P0 drops out, P3 joins. + // + // Each committee needs its own *PartyID copies because + // SortPartyIDs assigns Index based on sort position within + // the committee, and the same key may have different indices + // in different committees. + // ------------------------------------------------------------------ + allPIDs := tss.GenerateTestPartyIDs(4) + // Copy keys — each committee gets its own PartyID instances. + copyPID := func(src *tss.PartyID) *tss.PartyID { + return tss.NewPartyID(src.Id, src.Moniker, new(big.Int).SetBytes(src.Key)) + } + oldPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[0]), copyPID(allPIDs[1]), copyPID(allPIDs[2]), + }) + newPIDs := tss.SortPartyIDs(tss.UnSortedPartyIDs{ + copyPID(allPIDs[1]), copyPID(allPIDs[2]), copyPID(allPIDs[3]), + }) + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + oldN := len(oldPIDs) + newN := len(newPIDs) + + // ------------------------------------------------------------------ + // Step 2: Keygen (3 rounds, no Paillier needed for EdDSA) + // ------------------------------------------------------------------ + oldSaves := eddsaKeygen(t, oldN, threshold, oldPIDs, oldCtx) + pubKey := oldSaves[0].EDDSAPub + t.Logf("keygen: EDDSAPub = (%x, %x)", pubKey.X(), pubKey.Y()) + + // ------------------------------------------------------------------ + // Step 3: Sign with old committee + // ------------------------------------------------------------------ + msg1 := sha256.Sum256([]byte("pre-reshare message")) + sig1 := eddsaSign(t, oldN, threshold, oldPIDs, oldCtx, oldSaves, new(big.Int).SetBytes(msg1[:])) + verifyEdDSA(t, pubKey, msg1[:], sig1) + t.Log("pre-reshare signature verified") + + // ------------------------------------------------------------------ + // Step 4: Reshare — old [P0,P1,P2] → new [P1,P2,P3] + // + // 5 rounds. Each party participates based on which committee(s) + // it belongs to. P1 and P2 are in both (dual-committee). + // ------------------------------------------------------------------ + newSaves := eddsaReshare(t, oldPIDs, newPIDs, oldCtx, newCtx, + oldSaves, threshold, threshold) + + // Verify: same public key, all new saves valid. + for i := 0; i < newN; i++ { + if !newSaves[i].EDDSAPub.Equals(pubKey) { + t.Fatalf("new party %d: pub key changed after reshare", i) + } + if err := newSaves[i].ValidateSaveData(); err != nil { + t.Fatalf("new party %d: %v", i, err) + } + } + t.Log("reshare complete, pub key preserved") + + // Verify: old-only party (P0) had Xi zeroed. + if oldSaves[0].Xi.Sign() != 0 { + t.Fatal("P0 Xi not zeroed after reshare") + } + + // ------------------------------------------------------------------ + // Step 5: Sign with new committee + // ------------------------------------------------------------------ + msg2 := sha256.Sum256([]byte("post-reshare message")) + sig2 := eddsaSign(t, newN, threshold, newPIDs, newCtx, newSaves, new(big.Int).SetBytes(msg2[:])) + verifyEdDSA(t, pubKey, msg2[:], sig2) + t.Log("post-reshare signature verified") +} + +// --- helpers --- + +// ecPoint is a point on an elliptic curve with X and Y coordinates. +type ecPoint interface { + X() *big.Int + Y() *big.Int +} + +func verifyEdDSA(t *testing.T, pub ecPoint, msg []byte, sig *signing.SignatureData) { + t.Helper() + pk := edwards.PublicKey{Curve: tss.Edwards(), X: pub.X(), Y: pub.Y()} + r := new(big.Int).SetBytes(sig.R) + s := new(big.Int).SetBytes(sig.S) + if !edwards.Verify(&pk, msg, r, s) { + t.Fatal("EdDSA signature verification failed") + } +} + +func eddsaKeygen(t *testing.T, n, threshold int, pIDs tss.SortedPartyIDs, ctx *tss.PeerContext) []keygen.LocalPartySaveData { + t.Helper() + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), ctx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(params) + if err != nil { + t.Fatalf("keygen.Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(states[i], r1) + if err != nil { + t.Fatalf("keygen.Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("keygen.Round3[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves +} + +func eddsaSign(t *testing.T, n, threshold int, pIDs tss.SortedPartyIDs, ctx *tss.PeerContext, saves []keygen.LocalPartySaveData, m *big.Int) *signing.SignatureData { + t.Helper() + states := make([]*signing.SigningState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), ctx, pIDs[i], n, threshold) + st, out, err := signing.SignRound1(params, saves[i], m, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + r2 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound2(states[i], r1) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + r2[i] = out.Messages[0] + } + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := signing.SignRound3(states[i], r2) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + out, err := signing.SignFinalize(states[0], r3) + if err != nil { + t.Fatalf("SignFinalize: %v", err) + } + return out.Signature +} + +func eddsaReshare(t *testing.T, oldPIDs, newPIDs tss.SortedPartyIDs, oldCtx, newCtx *tss.PeerContext, oldSaves []keygen.LocalPartySaveData, oldT, newT int) []keygen.LocalPartySaveData { + t.Helper() + + oldN := len(oldPIDs) + newN := len(newPIDs) + + // Build a combined party list: every unique party participates. + type partyRole struct { + pid *tss.PartyID + oldIdx int // -1 if not in old committee + newIdx int // -1 if not in new committee + } + seen := make(map[string]*partyRole) + var allParties []*partyRole + for i, pid := range oldPIDs { + key := fmt.Sprintf("%x", pid.Key) + pr := &partyRole{pid: pid, oldIdx: i, newIdx: -1} + seen[key] = pr + allParties = append(allParties, pr) + } + for i, pid := range newPIDs { + key := fmt.Sprintf("%x", pid.Key) + if pr, ok := seen[key]; ok { + pr.newIdx = i // dual-committee + } else { + pr := &partyRole{pid: pid, oldIdx: -1, newIdx: i} + seen[key] = pr + allParties = append(allParties, pr) + } + } + + // --- Round 1 (old committee produces, new committee no-ops) --- + type stateEntry struct { + state *resharing.ReshareState + role *partyRole + } + entries := make([]stateEntry, len(allParties)) + r1Msgs := make([]*tss.Message, oldN) + + for idx, pr := range allParties { + params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, pr.pid, oldN, oldT, newN, newT) + var input *keygen.LocalPartySaveData + if pr.oldIdx >= 0 { + input = &oldSaves[pr.oldIdx] + } + st, out, err := resharing.ReshareRound1(params, input) + if err != nil { + t.Fatalf("ReshareRound1[%s]: %v", pr.pid.Id, err) + } + entries[idx] = stateEntry{state: st, role: pr} + if pr.oldIdx >= 0 && len(out.Messages) > 0 { + r1Msgs[pr.oldIdx] = out.Messages[0] + } + } + + // --- Round 2 (new committee sends ACK) --- + r2Msgs := make([]*tss.Message, newN) + for idx := range entries { + pr := entries[idx].role + out, err := resharing.ReshareRound2(entries[idx].state, r1Msgs) + if err != nil { + t.Fatalf("ReshareRound2[%s]: %v", pr.pid.Id, err) + } + if pr.newIdx >= 0 && len(out.Messages) > 0 { + r2Msgs[pr.newIdx] = out.Messages[0] + } + } + + // --- Round 3 (old committee sends shares + decommitment) --- + r3p2p := make([][]*tss.Message, newN) + r3bcast := make([]*tss.Message, oldN) + for i := range r3p2p { + r3p2p[i] = make([]*tss.Message, oldN) + } + for idx := range entries { + pr := entries[idx].role + out, err := resharing.ReshareRound3(entries[idx].state, r2Msgs) + if err != nil { + t.Fatalf("ReshareRound3[%s]: %v", pr.pid.Id, err) + } + if pr.oldIdx >= 0 { + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *resharing.DGRound3Message2: + r3bcast[pr.oldIdx] = msg + case *resharing.DGRound3Message1: + for _, to := range msg.To { + r3p2p[to.Index][pr.oldIdx] = msg + } + } + } + } + } + + // --- Round 4 (new committee verifies + ACK) --- + r4Msgs := make([]*tss.Message, newN) + for idx := range entries { + pr := entries[idx].role + var myP2P []*tss.Message + if pr.newIdx >= 0 { + myP2P = r3p2p[pr.newIdx] + } + out, err := resharing.ReshareRound4(entries[idx].state, r1Msgs, myP2P, r3bcast) + if err != nil { + t.Fatalf("ReshareRound4[%s]: %v", pr.pid.Id, err) + } + if pr.newIdx >= 0 && len(out.Messages) > 0 { + r4Msgs[pr.newIdx] = out.Messages[0] + } + } + + // --- Round 5 (save) --- + newSaves := make([]keygen.LocalPartySaveData, newN) + for idx := range entries { + pr := entries[idx].role + out, err := resharing.ReshareRound5(entries[idx].state, r4Msgs) + if err != nil { + t.Fatalf("ReshareRound5[%s]: %v", pr.pid.Id, err) + } + if pr.newIdx >= 0 { + newSaves[pr.newIdx] = *out.Save + } + } + + return newSaves +} diff --git a/tss-lib/eddsa/keygen/eddsa-keygen.pb.go b/tss-lib/eddsa/keygen/eddsa-keygen.pb.go deleted file mode 100644 index 84327b8..0000000 --- a/tss-lib/eddsa/keygen/eddsa-keygen.pb.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.14.0 -// source: protob/eddsa-keygen.proto - -package keygen - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// -// Represents a BROADCAST message sent during Round 1 of the EDDSA TSS keygen protocol. -type KGRound1Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` -} - -func (x *KGRound1Message) Reset() { - *x = KGRound1Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_keygen_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound1Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound1Message) ProtoMessage() {} - -func (x *KGRound1Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_keygen_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound1Message.ProtoReflect.Descriptor instead. -func (*KGRound1Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_keygen_proto_rawDescGZIP(), []int{0} -} - -func (x *KGRound1Message) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -// -// Represents a P2P message sent to each party during Round 2 of the EDDSA TSS keygen protocol. -type KGRound2Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Share []byte `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"` -} - -func (x *KGRound2Message1) Reset() { - *x = KGRound2Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_keygen_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound2Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound2Message1) ProtoMessage() {} - -func (x *KGRound2Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_keygen_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound2Message1.ProtoReflect.Descriptor instead. -func (*KGRound2Message1) Descriptor() ([]byte, []int) { - return file_protob_eddsa_keygen_proto_rawDescGZIP(), []int{1} -} - -func (x *KGRound2Message1) GetShare() []byte { - if x != nil { - return x.Share - } - return nil -} - -// -// Represents a BROADCAST message sent to each party during Round 2 of the EDDSA TSS keygen protocol. -type KGRound2Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeCommitment [][]byte `protobuf:"bytes,1,rep,name=de_commitment,json=deCommitment,proto3" json:"de_commitment,omitempty"` - ProofAlphaX []byte `protobuf:"bytes,2,opt,name=proof_alpha_x,json=proofAlphaX,proto3" json:"proof_alpha_x,omitempty"` - ProofAlphaY []byte `protobuf:"bytes,3,opt,name=proof_alpha_y,json=proofAlphaY,proto3" json:"proof_alpha_y,omitempty"` - ProofT []byte `protobuf:"bytes,4,opt,name=proof_t,json=proofT,proto3" json:"proof_t,omitempty"` -} - -func (x *KGRound2Message2) Reset() { - *x = KGRound2Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_keygen_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KGRound2Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KGRound2Message2) ProtoMessage() {} - -func (x *KGRound2Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_keygen_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KGRound2Message2.ProtoReflect.Descriptor instead. -func (*KGRound2Message2) Descriptor() ([]byte, []int) { - return file_protob_eddsa_keygen_proto_rawDescGZIP(), []int{2} -} - -func (x *KGRound2Message2) GetDeCommitment() [][]byte { - if x != nil { - return x.DeCommitment - } - return nil -} - -func (x *KGRound2Message2) GetProofAlphaX() []byte { - if x != nil { - return x.ProofAlphaX - } - return nil -} - -func (x *KGRound2Message2) GetProofAlphaY() []byte { - if x != nil { - return x.ProofAlphaY - } - return nil -} - -func (x *KGRound2Message2) GetProofT() []byte { - if x != nil { - return x.ProofT - } - return nil -} - -var File_protob_eddsa_keygen_proto protoreflect.FileDescriptor - -var file_protob_eddsa_keygen_proto_rawDesc = []byte{ - 0x0a, 0x19, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x65, 0x64, 0x64, 0x73, 0x61, 0x2d, 0x6b, - 0x65, 0x79, 0x67, 0x65, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x62, 0x69, 0x6e, - 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x64, 0x64, 0x73, - 0x61, 0x2e, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x22, 0x31, 0x0a, 0x0f, 0x4b, 0x47, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x28, 0x0a, 0x10, 0x4b, - 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x10, 0x4b, 0x47, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x32, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, - 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, - 0x68, 0x61, 0x58, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x5f, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x59, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x5f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, - 0x42, 0x0e, 0x5a, 0x0c, 0x65, 0x64, 0x64, 0x73, 0x61, 0x2f, 0x6b, 0x65, 0x79, 0x67, 0x65, 0x6e, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_protob_eddsa_keygen_proto_rawDescOnce sync.Once - file_protob_eddsa_keygen_proto_rawDescData = file_protob_eddsa_keygen_proto_rawDesc -) - -func file_protob_eddsa_keygen_proto_rawDescGZIP() []byte { - file_protob_eddsa_keygen_proto_rawDescOnce.Do(func() { - file_protob_eddsa_keygen_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_eddsa_keygen_proto_rawDescData) - }) - return file_protob_eddsa_keygen_proto_rawDescData -} - -var file_protob_eddsa_keygen_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_protob_eddsa_keygen_proto_goTypes = []interface{}{ - (*KGRound1Message)(nil), // 0: binance.tsslib.eddsa.keygen.KGRound1Message - (*KGRound2Message1)(nil), // 1: binance.tsslib.eddsa.keygen.KGRound2Message1 - (*KGRound2Message2)(nil), // 2: binance.tsslib.eddsa.keygen.KGRound2Message2 -} -var file_protob_eddsa_keygen_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_protob_eddsa_keygen_proto_init() } -func file_protob_eddsa_keygen_proto_init() { - if File_protob_eddsa_keygen_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_eddsa_keygen_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound1Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_keygen_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound2Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_keygen_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KGRound2Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_eddsa_keygen_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_eddsa_keygen_proto_goTypes, - DependencyIndexes: file_protob_eddsa_keygen_proto_depIdxs, - MessageInfos: file_protob_eddsa_keygen_proto_msgTypes, - }.Build() - File_protob_eddsa_keygen_proto = out.File - file_protob_eddsa_keygen_proto_rawDesc = nil - file_protob_eddsa_keygen_proto_goTypes = nil - file_protob_eddsa_keygen_proto_depIdxs = nil -} diff --git a/tss-lib/eddsa/keygen/local_party.go b/tss-lib/eddsa/keygen/local_party.go deleted file mode 100644 index f3b6479..0000000 --- a/tss-lib/eddsa/keygen/local_party.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Implements Party -// Implements Stringer -var _ tss.Party = (*LocalParty)(nil) -var _ fmt.Stringer = (*LocalParty)(nil) - -type ( - LocalParty struct { - *tss.BaseParty - params *tss.Parameters - - temp localTempData - data LocalPartySaveData - - // outbound messaging - out chan<- tss.Message - end chan<- *LocalPartySaveData - } - - localMessageStore struct { - kgRound1Messages, - kgRound2Message1s, - kgRound2Message2s, - kgRound3Messages []tss.ParsedMessage - } - - localTempData struct { - localMessageStore - - // temp data (thrown away after keygen) - ui *big.Int // used for tests - KGCs []cmt.HashCommitment - vs vss.Vs - shares vss.Shares - deCommitPolyG cmt.HashDeCommitment - - ssid []byte - ssidNonce *big.Int - } -) - -// Exported, used in `tss` client -func NewLocalParty( - params *tss.Parameters, - out chan<- tss.Message, - end chan<- *LocalPartySaveData, -) tss.Party { - partyCount := params.PartyCount() - data := NewLocalPartySaveData(partyCount) - p := &LocalParty{ - BaseParty: new(tss.BaseParty), - params: params, - temp: localTempData{}, - data: data, - out: out, - end: end, - } - // msgs init - p.temp.kgRound1Messages = make([]tss.ParsedMessage, partyCount) - p.temp.kgRound2Message1s = make([]tss.ParsedMessage, partyCount) - p.temp.kgRound2Message2s = make([]tss.ParsedMessage, partyCount) - p.temp.kgRound3Messages = make([]tss.ParsedMessage, partyCount) - // temp data init - p.temp.KGCs = make([]cmt.HashCommitment, partyCount) - return p -} - -func (p *LocalParty) FirstRound() tss.Round { - return newRound1(p.params, &p.data, &p.temp, p.out, p.end) -} - -func (p *LocalParty) Start() *tss.Error { - return tss.BaseStart(p, TaskName) -} - -func (p *LocalParty) Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) { - return tss.BaseUpdate(p, msg, TaskName) -} - -func (p *LocalParty) UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (bool, *tss.Error) { - msg, err := tss.ParseWireMessage(wireBytes, from, isBroadcast) - if err != nil { - return false, p.WrapError(err) - } - return p.Update(msg) -} - -func (p *LocalParty) ValidateMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - if ok, err := p.BaseParty.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - // check that the message's "from index" will fit into the array - if maxFromIdx := p.params.PartyCount() - 1; maxFromIdx < msg.GetFrom().Index { - return false, p.WrapError(fmt.Errorf("received msg with a sender index too great (%d <= %d)", - p.params.PartyCount(), msg.GetFrom().Index), msg.GetFrom()) - } - return true, nil -} - -func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - // ValidateBasic is cheap; double-check the message here in case the public StoreMessage was called externally - if ok, err := p.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - fromPIdx := msg.GetFrom().Index - - // switch/case is necessary to store any messages beyond current round - // this does not handle message replays. we expect the caller to apply replay and spoofing protection. - switch msg.Content().(type) { - case *KGRound1Message: - p.temp.kgRound1Messages[fromPIdx] = msg - case *KGRound2Message1: - p.temp.kgRound2Message1s[fromPIdx] = msg - case *KGRound2Message2: - p.temp.kgRound2Message2s[fromPIdx] = msg - default: // unrecognised message, just ignore! - common.Logger.Warningf("unrecognised message ignored: %v", msg) - return false, nil - } - return true, nil -} - -// recovers a party's original index in the set of parties during keygen -func (save LocalPartySaveData) OriginalIndex() (int, error) { - index := -1 - ki := save.ShareID - for j, kj := range save.Ks { - if kj.Cmp(ki) != 0 { - continue - } - index = j - break - } - if index < 0 { - return -1, errors.New("a party index could not be recovered from Ks") - } - return index, nil -} - -func (p *LocalParty) PartyID() *tss.PartyID { - return p.params.PartyID() -} - -func (p *LocalParty) String() string { - return fmt.Sprintf("id: %s, %s", p.PartyID(), p.BaseParty.String()) -} diff --git a/tss-lib/eddsa/keygen/local_party_test.go b/tss-lib/eddsa/keygen/local_party_test.go deleted file mode 100644 index 2081f45..0000000 --- a/tss-lib/eddsa/keygen/local_party_test.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "encoding/json" - "fmt" - "math/big" - "os" - "runtime" - "sync/atomic" - "testing" - - "github.com/decred/dcrd/dcrec/edwards/v2" - "github.com/ipfs/go-log" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - testParticipants = TestParticipants - testThreshold = TestThreshold -) - -func setUp(level string) { - if err := log.SetLogLevel("tss-lib", level); err != nil { - panic(err) - } -} - -func TestE2EConcurrentAndSaveFixtures(t *testing.T) { - setUp("info") - - threshold := testThreshold - fixtures, pIDs, err := LoadKeygenTestFixtures(testParticipants) - if err != nil { - common.Logger.Info("No test fixtures were found, so the safe primes will be generated from scratch. This may take a while...") - pIDs = tss.GenerateTestPartyIDs(testParticipants) - } - - p2pCtx := tss.NewPeerContext(pIDs) - parties := make([]*LocalParty, 0, len(pIDs)) - - errCh := make(chan *tss.Error, len(pIDs)) - outCh := make(chan tss.Message, len(pIDs)) - endCh := make(chan *LocalPartySaveData, len(pIDs)) - - updater := test.SharedPartyUpdater - - startGR := runtime.NumGoroutine() - - // init the parties - for i := 0; i < len(pIDs); i++ { - var P *LocalParty - params := tss.NewParameters(tss.Edwards(), p2pCtx, pIDs[i], len(pIDs), threshold) - if i < len(fixtures) { - P = NewLocalParty(params, outCh, endCh).(*LocalParty) - } else { - P = NewLocalParty(params, outCh, endCh).(*LocalParty) - } - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - // PHASE: keygen - var ended int32 -keygen: - for { - fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break keygen - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { // broadcast! - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { // point-to-point! - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - return - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case save := <-endCh: - // SAVE a test fixture file for this P (if it doesn't already exist) - // .. here comes a workaround to recover this party's index (it was removed from save data) - index, err := save.OriginalIndex() - assert.NoErrorf(t, err, "should not be an error getting a party's index from save data") - tryWriteTestFixtureFile(t, index, *save) - - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(pIDs)) { - t.Logf("Done. Received save data from %d participants", ended) - - // combine shares for each Pj to get u - u := new(big.Int) - for j, Pj := range parties { - pShares := make(vss.Shares, 0) - for j2, P := range parties { - if j2 == j { - continue - } - vssMsgs := P.temp.kgRound2Message1s - share := vssMsgs[j].Content().(*KGRound2Message1).Share - shareStruct := &vss.Share{ - Threshold: threshold, - ID: P.PartyID().KeyInt(), - Share: new(big.Int).SetBytes(share), - } - pShares = append(pShares, shareStruct) - } - uj, err := pShares[:threshold+1].ReConstruct(tss.Edwards()) - assert.NoError(t, err, "vss.ReConstruct should not throw error") - - // uG test: u*G[j] == V[0] - assert.Equal(t, uj, Pj.temp.ui) - uG := crypto.ScalarBaseMult(tss.Edwards(), uj) - assert.True(t, uG.Equals(Pj.temp.vs[0]), "ensure u*G[j] == V_0") - - // xj tests: BigXj == xj*G - xj := Pj.data.Xi - gXj := crypto.ScalarBaseMult(tss.Edwards(), xj) - BigXj := Pj.data.BigXj[j] - assert.True(t, BigXj.Equals(gXj), "ensure BigX_j == g^x_j") - - // fails if threshold cannot be satisfied (bad share) - { - badShares := pShares[:threshold] - badShares[len(badShares)-1].Share.Set(big.NewInt(0)) - uj, err := pShares[:threshold].ReConstruct(tss.Edwards()) - assert.NoError(t, err) - assert.NotEqual(t, parties[j].temp.ui, uj) - BigXjX, BigXjY := tss.Edwards().ScalarBaseMult(uj.Bytes()) - assert.NotEqual(t, BigXjX, Pj.temp.vs[0].X()) - assert.NotEqual(t, BigXjY, Pj.temp.vs[0].Y()) - } - u = new(big.Int).Add(u, uj) - } - u = new(big.Int).Mod(u, tss.Edwards().Params().N) - scalar := make([]byte, 0, 32) - copy(scalar, u.Bytes()) - - // build eddsa key pair - pkX, pkY := save.EDDSAPub.X(), save.EDDSAPub.Y() - pk := edwards.PublicKey{ - Curve: tss.Edwards(), - X: pkX, - Y: pkY, - } - println("u len: ", len(u.Bytes())) - sk, _, err := edwards.PrivKeyFromScalar(common.PadToLengthBytesInPlace(u.Bytes(), 32)) - if !assert.NoError(t, err) { - return - } - - // test pub key, should be on curve and match pkX, pkY - assert.True(t, pk.IsOnCurve(pkX, pkY), "public key must be on curve") - - // public key tests - assert.NotZero(t, u, "u should not be zero") - ourPkX, ourPkY := tss.Edwards().ScalarBaseMult(u.Bytes()) - assert.Equal(t, pkX, ourPkX, "pkX should match expected pk derived from u") - assert.Equal(t, pkY, ourPkY, "pkY should match expected pk derived from u") - t.Log("Public key tests done.") - - // make sure everyone has the same EDDSA public key - for _, Pj := range parties { - assert.Equal(t, pkX, Pj.data.EDDSAPub.X()) - assert.Equal(t, pkY, Pj.data.EDDSAPub.Y()) - } - t.Log("Public key distribution test done.") - - // test sign/verify - data := make([]byte, 32) - for i := range data { - data[i] = byte(i) - } - r, s, err := edwards.Sign(sk, data) - assert.NoError(t, err, "sign should not throw an error") - ok := edwards.Verify(&pk, data, r, s) - assert.True(t, ok, "signature should be ok") - t.Log("EDDSA signing test done.") - - t.Logf("Start goroutines: %d, End goroutines: %d", startGR, runtime.NumGoroutine()) - - break keygen - } - } - } -} - -func tryWriteTestFixtureFile(t *testing.T, index int, data LocalPartySaveData) { - fixtureFileName := makeTestFixtureFilePath(index) - - // fixture file does not already exist? - // if it does, we won't re-create it here - fi, err := os.Stat(fixtureFileName) - if !(err == nil && fi != nil && !fi.IsDir()) { - fd, err := os.OpenFile(fixtureFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - assert.NoErrorf(t, err, "unable to open fixture file %s for writing", fixtureFileName) - } - bz, err := json.Marshal(&data) - if err != nil { - t.Fatalf("unable to marshal save data for fixture file %s", fixtureFileName) - } - _, err = fd.Write(bz) - if err != nil { - t.Fatalf("unable to write to fixture file %s", fixtureFileName) - } - t.Logf("Saved a test fixture file for party %d: %s", index, fixtureFileName) - } else { - t.Logf("Fixture file already exists for party %d; not re-creating: %s", index, fixtureFileName) - } - // -} diff --git a/tss-lib/eddsa/keygen/messages.go b/tss-lib/eddsa/keygen/messages.go index a8d9a53..452900d 100644 --- a/tss-lib/eddsa/keygen/messages.go +++ b/tss-lib/eddsa/keygen/messages.go @@ -1,126 +1,83 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen import ( - "crypto/elliptic" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -// These messages were generated from Protocol Buffers definitions into eddsa-keygen.pb.go -// The following messages are registered on the Protocol Buffers "wire" - -var ( - // Ensure that keygen messages implement ValidateBasic - _ = []tss.MessageContent{ - (*KGRound1Message)(nil), - (*KGRound2Message1)(nil), - (*KGRound2Message2)(nil), - } -) - -// ----- // - -func NewKGRound1Message(from *tss.PartyID, ct cmt.HashCommitment) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - IsBroadcast: true, - } - content := &KGRound1Message{ - Commitment: ct.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// KGRound1Message is broadcast: VSS commitment hash. +type KGRound1Message struct { + Commitment *big.Int } +// ValidateBasic checks that required fields of KGRound1Message are non-nil. func (m *KGRound1Message) ValidateBasic() bool { - return m != nil && common.NonEmptyBytes(m.GetCommitment()) + return m != nil && m.Commitment != nil && m.Commitment.Sign() > 0 } -func (m *KGRound1Message) UnmarshalCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetCommitment()) -} - -// ----- // - -func NewKGRound2Message1( - to, from *tss.PartyID, - share *vss.Share, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewKGRound1Message constructs a *tss.Message with the given content. +func NewKGRound1Message(from *tss.PartyID, ct cmt.HashCommitment) *tss.Message { + return &tss.Message{ From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - } - content := &KGRound2Message1{ - Share: share.Share.Bytes(), + IsBroadcast: true, + Content: &KGRound1Message{ + Commitment: ct, + }, } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *KGRound2Message1) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.GetShare()) +// KGRound2Message1 is P2P: VSS share + receiver binding. +type KGRound2Message1 struct { + Share *big.Int + ReceiverID []byte } -func (m *KGRound2Message1) UnmarshalShare() *big.Int { - return new(big.Int).SetBytes(m.Share) +// ValidateBasic checks that required fields of KGRound2Message1 are non-nil. +func (m *KGRound2Message1) ValidateBasic() bool { + return m != nil && m.Share != nil && m.Share.Sign() > 0 && + len(m.ReceiverID) > 0 } -// ----- // - -func NewKGRound2Message2( - from *tss.PartyID, - deCommitment cmt.HashDeCommitment, - proof *schnorr.ZKProof, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - IsBroadcast: true, - } - dcBzs := common.BigIntsToBytes(deCommitment) - content := &KGRound2Message2{ - DeCommitment: dcBzs, - ProofAlphaX: proof.Alpha.X().Bytes(), - ProofAlphaY: proof.Alpha.Y().Bytes(), - ProofT: proof.T.Bytes(), +// NewKGRound2Message1 constructs a *tss.Message with the given content. +func NewKGRound2Message1(to, from *tss.PartyID, share *vss.Share) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &KGRound2Message1{ + Share: share.Share, + ReceiverID: to.Key, + }, } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *KGRound2Message2) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.GetDeCommitment()) +// KGRound2Message2 is broadcast: decommitment + Schnorr proof. +type KGRound2Message2 struct { + DeCommitment cmt.HashDeCommitment + ZKProof *schnorr.ZKProof } -func (m *KGRound2Message2) UnmarshalDeCommitment() []*big.Int { - deComBzs := m.GetDeCommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) +// ValidateBasic checks that required fields of KGRound2Message2 are non-nil. +func (m *KGRound2Message2) ValidateBasic() bool { + return m != nil && len(m.DeCommitment) >= 2 && m.ZKProof != nil } -func (m *KGRound2Message2) UnmarshalZKProof(ec elliptic.Curve) (*schnorr.ZKProof, error) { - point, err := crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.GetProofAlphaX()), - new(big.Int).SetBytes(m.GetProofAlphaY())) - if err != nil { - return nil, err +// NewKGRound2Message2 constructs a *tss.Message with the given content. +func NewKGRound2Message2(from *tss.PartyID, deCommitment cmt.HashDeCommitment, proof *schnorr.ZKProof) *tss.Message { + return &tss.Message{ + From: from, + IsBroadcast: true, + Content: &KGRound2Message2{ + DeCommitment: deCommitment, + ZKProof: proof, + }, } - return &schnorr.ZKProof{ - Alpha: point, - T: new(big.Int).SetBytes(m.GetProofT()), - }, nil } diff --git a/tss-lib/eddsa/keygen/negative_test.go b/tss-lib/eddsa/keygen/negative_test.go new file mode 100644 index 0000000..5fc8bc7 --- /dev/null +++ b/tss-lib/eddsa/keygen/negative_test.go @@ -0,0 +1,242 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// runEdDSAKeygen runs a full 3-party keygen, returning states, round messages. +func runEdDSAKeygen(t *testing.T) (states []*KeygenState, r1 []*tss.Message, r2p2p [][]*tss.Message, r2bcast []*tss.Message, pIDs tss.SortedPartyIDs) { + t.Helper() + const n = 3 + const threshold = 1 + + pIDs = tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states = make([]*KeygenState, n) + r1 = make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := Round1(params) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2p2p = make([][]*tss.Message, n) + r2bcast = make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := Round2(states[i], r1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + return +} + +func TestRound2InvalidR1Message(t *testing.T) { + const n = 3 + const threshold = 1 + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states := make([]*KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := Round1(params) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + // Corrupt r1[1]: nil commitment + r1Bad := make([]*tss.Message, n) + copy(r1Bad, r1) + r1Bad[1] = &tss.Message{ + From: r1[1].From, + Content: &KGRound1Message{Commitment: nil}, // invalid + } + + _, err := Round2(states[0], r1Bad) + if err == nil { + t.Fatal("expected error for invalid round 1 message") + } +} + +func TestRound3BadDeCommitment(t *testing.T) { + states, _, r2p2p, r2bcast, _ := runEdDSAKeygen(t) + + // Corrupt decommitment for party 1 → should fail party 0's Round3 + badBcast := make([]*tss.Message, len(r2bcast)) + copy(badBcast, r2bcast) + badContent := *r2bcast[1].Content.(*KGRound2Message2) + badContent.DeCommitment = nil + badBcast[1] = &tss.Message{From: r2bcast[1].From, Content: &badContent} + + _, err := Round3(states[0], r2p2p[0], badBcast) + if err == nil { + t.Fatal("expected error for bad decommitment") + } +} + +func TestRound3MissingSchnorrProof(t *testing.T) { + states, _, r2p2p, r2bcast, _ := runEdDSAKeygen(t) + + badBcast := make([]*tss.Message, len(r2bcast)) + copy(badBcast, r2bcast) + badContent := *r2bcast[1].Content.(*KGRound2Message2) + badContent.ZKProof = nil + badBcast[1] = &tss.Message{From: r2bcast[1].From, Content: &badContent} + + _, err := Round3(states[0], r2p2p[0], badBcast) + if err == nil { + t.Fatal("expected error for missing schnorr proof") + } +} + +func TestRound3WrongSchnorrProof(t *testing.T) { + states, _, r2p2p, r2bcast, _ := runEdDSAKeygen(t) + + badBcast := make([]*tss.Message, len(r2bcast)) + copy(badBcast, r2bcast) + badContent := *r2bcast[1].Content.(*KGRound2Message2) + // Replace with a random proof that won't verify + badContent.ZKProof = &schnorr.ZKProof{Alpha: nil, T: big.NewInt(42)} + badBcast[1] = &tss.Message{From: r2bcast[1].From, Content: &badContent} + + _, err := Round3(states[0], r2p2p[0], badBcast) + if err == nil { + t.Fatal("expected error for wrong schnorr proof") + } +} + +func TestRound3WrongReceiverID(t *testing.T) { + states, _, r2p2p, r2bcast, _ := runEdDSAKeygen(t) + + // Corrupt receiverID on the P2P message from party 1 to party 0 + badP2P := make([]*tss.Message, len(r2p2p[0])) + copy(badP2P, r2p2p[0]) + badContent := *r2p2p[0][1].Content.(*KGRound2Message1) + badContent.ReceiverID = []byte("wrong") + badP2P[1] = &tss.Message{From: r2p2p[0][1].From, Content: &badContent} + + _, err := Round3(states[0], badP2P, r2bcast) + if err == nil { + t.Fatal("expected error for wrong receiverID") + } +} + +func TestRound3BadVSSShare(t *testing.T) { + states, _, r2p2p, r2bcast, _ := runEdDSAKeygen(t) + + // Corrupt share value from party 1 → party 0 + badP2P := make([]*tss.Message, len(r2p2p[0])) + copy(badP2P, r2p2p[0]) + badContent := *r2p2p[0][1].Content.(*KGRound2Message1) + badContent.Share = new(big.Int).Add(badContent.Share, big.NewInt(999)) + badP2P[1] = &tss.Message{From: r2p2p[0][1].From, Content: &badContent} + + _, err := Round3(states[0], badP2P, r2bcast) + if err == nil { + t.Fatal("expected error for bad VSS share") + } +} + +func TestValidateSaveDataEdDSA(t *testing.T) { + states, _, r2p2p, r2bcast, _ := runEdDSAKeygen(t) + + out, err := Round3(states[0], r2p2p[0], r2bcast) + if err != nil { + t.Fatalf("Round3: %v", err) + } + if err := out.Save.ValidateSaveData(); err != nil { + t.Fatalf("ValidateSaveData should pass: %v", err) + } + + // Test each failure path + bad := *out.Save + bad.EDDSAPub = nil + if err := bad.ValidateSaveData(); err == nil { + t.Fatal("expected error for nil EDDSAPub") + } + bad = *out.Save + bad.Xi = nil + if err := bad.ValidateSaveData(); err == nil { + t.Fatal("expected error for nil Xi") + } + bad = *out.Save + bad.Xi = big.NewInt(0) + if err := bad.ValidateSaveData(); err == nil { + t.Fatal("expected error for zero Xi") + } + bad = *out.Save + bad.ShareID = nil + if err := bad.ValidateSaveData(); err == nil { + t.Fatal("expected error for nil ShareID") + } + bad = *out.Save + bad.Ks = nil + if err := bad.ValidateSaveData(); err == nil { + t.Fatal("expected error for nil Ks") + } + bad = *out.Save + bad.BigXj = nil + if err := bad.ValidateSaveData(); err == nil { + t.Fatal("expected error for nil BigXj") + } +} + +func TestBuildLocalSaveDataSubsetEdDSA(t *testing.T) { + states, _, r2p2p, r2bcast, pIDs := runEdDSAKeygen(t) + + out, err := Round3(states[0], r2p2p[0], r2bcast) + if err != nil { + t.Fatalf("Round3: %v", err) + } + + // Subset to 2-of-3 + subset := BuildLocalSaveDataSubset(*out.Save, pIDs[:2]) + if len(subset.Ks) != 2 { + t.Fatalf("expected 2 Ks, got %d", len(subset.Ks)) + } + + // Missing key should panic + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("expected panic for missing signer key") + } + }() + fakeIDs := tss.GenerateTestPartyIDs(1) + BuildLocalSaveDataSubset(*out.Save, fakeIDs) + }() +} diff --git a/tss-lib/eddsa/keygen/round_1.go b/tss-lib/eddsa/keygen/round_1.go deleted file mode 100644 index 2205d33..0000000 --- a/tss-lib/eddsa/keygen/round_1.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmts "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -var zero = big.NewInt(0) - -// round 1 represents round 1 of the keygen part of the EDDSA TSS spec -func newRound1(params *tss.Parameters, save *LocalPartySaveData, temp *localTempData, out chan<- tss.Message, end chan<- *LocalPartySaveData) tss.Round { - return &round1{ - &base{params, save, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 1}, - } -} - -func (round *round1) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 1 - round.started = true - round.resetOK() - - Pi := round.PartyID() - i := Pi.Index - - round.temp.ssidNonce = new(big.Int).SetUint64(0) - ssid, err := round.getSSID() - if err != nil { - return round.WrapError(err) - } - round.temp.ssid = ssid - - // 1. calculate "partial" key share ui - ui := common.GetRandomPositiveInt(round.PartialKeyRand(), round.Params().EC().Params().N) - round.temp.ui = ui - - // 2. compute the vss shares - ids := round.Parties().IDs().Keys() - vs, shares, err := vss.Create(round.EC(), round.Threshold(), ui, ids, round.Rand()) - if err != nil { - return round.WrapError(err, Pi) - } - round.save.Ks = ids - - // security: the original u_i may be discarded - ui = zero // clears the secret data from memory - _ = ui // silences a linter warning - - // 3. make commitment -> (C, D) - pGFlat, err := crypto.FlattenECPoints(vs) - if err != nil { - return round.WrapError(err, Pi) - } - cmt := cmts.NewHashCommitment(round.Rand(), pGFlat...) - - // for this P: SAVE - // - shareID - // and keep in temporary storage: - // - VSS Vs - // - our set of Shamir shares - round.save.ShareID = ids[i] - round.temp.vs = vs - round.temp.shares = shares - - round.temp.deCommitPolyG = cmt.D - - // BROADCAST commitments - { - msg := NewKGRound1Message(round.PartyID(), cmt.C) - round.temp.kgRound1Messages[i] = msg - round.out <- msg - } - return nil -} - -func (round *round1) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*KGRound1Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round1) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.kgRound1Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - // vss check is in round 2 - round.ok[j] = true - } - return ret, nil -} - -func (round *round1) NextRound() tss.Round { - round.started = false - return &round2{round} -} diff --git a/tss-lib/eddsa/keygen/round_2.go b/tss-lib/eddsa/keygen/round_2.go deleted file mode 100644 index bd55c09..0000000 --- a/tss-lib/eddsa/keygen/round_2.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - "math/big" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round2) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 2 - round.started = true - round.resetOK() - - i := round.PartyID().Index - - // 4. store r1 message pieces - for j, msg := range round.temp.kgRound1Messages { - r1msg := msg.Content().(*KGRound1Message) - round.temp.KGCs[j] = r1msg.UnmarshalCommitment() - } - - // 3. p2p send share ij to Pj - shares := round.temp.shares - for j, Pj := range round.Parties().IDs() { - r2msg1 := NewKGRound2Message1(Pj, round.PartyID(), shares[j]) - // do not send to this Pj, but store for round 3 - if j == i { - round.temp.kgRound2Message1s[j] = r2msg1 - continue - } - round.temp.kgRound2Message1s[i] = r2msg1 - round.out <- r2msg1 - } - - // 5. compute Schnorr prove - ContextI := append(round.temp.ssid, new(big.Int).SetUint64(uint64(i)).Bytes()...) - pii, err := schnorr.NewZKProof(ContextI, round.temp.ui, round.temp.vs[0], round.Rand()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewZKProof(ui, vi0)")) - } - - // 5. BROADCAST de-commitments of Shamir poly*G and Schnorr prove - r2msg2 := NewKGRound2Message2(round.PartyID(), round.temp.deCommitPolyG, pii) - round.temp.kgRound2Message2s[i] = r2msg2 - round.out <- r2msg2 - - return nil -} - -func (round *round2) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*KGRound2Message1); ok { - return !msg.IsBroadcast() - } - if _, ok := msg.Content().(*KGRound2Message2); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round2) Update() (bool, *tss.Error) { - // guard - VERIFY de-commit for all Pj - ret := true - for j, msg := range round.temp.kgRound2Message1s { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - msg2 := round.temp.kgRound2Message2s[j] - if msg2 == nil || !round.CanAccept(msg2) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round2) NextRound() tss.Round { - round.started = false - return &round3{round} -} diff --git a/tss-lib/eddsa/keygen/round_3.go b/tss-lib/eddsa/keygen/round_3.go deleted file mode 100644 index 47d4383..0000000 --- a/tss-lib/eddsa/keygen/round_3.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "errors" - "math/big" - - "github.com/hashicorp/go-multierror" - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round3) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 3 - round.started = true - round.resetOK() - - Ps := round.Parties().IDs() - PIdx := round.PartyID().Index - - // 1,10. calculate xi - xi := new(big.Int).Set(round.temp.shares[PIdx].Share) - for j := range Ps { - if j == PIdx { - continue - } - r2msg1 := round.temp.kgRound2Message1s[j].Content().(*KGRound2Message1) - share := r2msg1.UnmarshalShare() - xi = new(big.Int).Add(xi, share) - } - round.save.Xi = new(big.Int).Mod(xi, round.Params().EC().Params().N) - - // 2-3. - Vc := make(vss.Vs, round.Threshold()+1) - for c := range Vc { - Vc[c] = round.temp.vs[c] // ours - } - - // 4-12. - type vssOut struct { - unWrappedErr error - pjVs vss.Vs - } - chs := make([]chan vssOut, len(Ps)) - for i := range chs { - if i == PIdx { - continue - } - chs[i] = make(chan vssOut) - } - for j := range Ps { - if j == PIdx { - continue - } - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - - // 6-9. - go func(j int, ch chan<- vssOut) { - // 4-10. - KGCj := round.temp.KGCs[j] - r2msg2 := round.temp.kgRound2Message2s[j].Content().(*KGRound2Message2) - KGDj := r2msg2.UnmarshalDeCommitment() - cmtDeCmt := commitments.HashCommitDecommit{C: KGCj, D: KGDj} - ok, flatPolyGs := cmtDeCmt.DeCommit() - if !ok || flatPolyGs == nil { - ch <- vssOut{errors.New("de-commitment verify failed"), nil} - return - } - - PjVs, err := crypto.UnFlattenECPoints(round.Params().EC(), flatPolyGs) - for i, PjV := range PjVs { - PjVs[i] = PjV.EightInvEight() - } - - if err != nil { - ch <- vssOut{err, nil} - return - } - proof, err := r2msg2.UnmarshalZKProof(round.Params().EC()) - if err != nil { - ch <- vssOut{errors.New("failed to unmarshal schnorr proof"), nil} - return - } - ok = proof.Verify(ContextJ, PjVs[0]) - if !ok { - ch <- vssOut{errors.New("failed to prove schnorr proof"), nil} - return - } - r2msg1 := round.temp.kgRound2Message1s[j].Content().(*KGRound2Message1) - PjShare := vss.Share{ - Threshold: round.Threshold(), - ID: round.PartyID().KeyInt(), - Share: r2msg1.UnmarshalShare(), - } - if ok = PjShare.Verify(round.Params().EC(), round.Threshold(), PjVs); !ok { - ch <- vssOut{errors.New("vss verify failed"), nil} - return - } - // (9) handled above - ch <- vssOut{nil, PjVs} - }(j, chs[j]) - } - - // consume unbuffered channels (end the goroutines) - vssResults := make([]vssOut, len(Ps)) - { - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - for j, Pj := range Ps { - if j == PIdx { - continue - } - vssResults[j] = <-chs[j] - // collect culprits to error out with - if err := vssResults[j].unWrappedErr; err != nil { - culprits = append(culprits, Pj) - } - } - var multiErr error - if len(culprits) > 0 { - for _, vssResult := range vssResults { - if vssResult.unWrappedErr != nil { - multiErr = multierror.Append(multiErr, vssResult.unWrappedErr) - } - } - return round.WrapError(multiErr, culprits...) - } - } - { - var err error - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - for j, Pj := range Ps { - if j == PIdx { - continue - } - // 11-12. - PjVs := vssResults[j].pjVs - for c := 0; c <= round.Threshold(); c++ { - Vc[c], err = Vc[c].Add(PjVs[c]) - if err != nil { - culprits = append(culprits, Pj) - } - } - } - if len(culprits) > 0 { - return round.WrapError(errors.New("adding PjVs[c] to Vc[c] resulted in a point not on the curve"), culprits...) - } - } - - // 13-17. compute Xj for each Pj - { - var err error - modQ := common.ModInt(round.Params().EC().Params().N) - culprits := make([]*tss.PartyID, 0, len(Ps)) // who caused the error(s) - bigXj := round.save.BigXj - for j := 0; j < round.PartyCount(); j++ { - Pj := round.Parties().IDs()[j] - kj := Pj.KeyInt() - BigXj := Vc[0] - z := new(big.Int).SetInt64(int64(1)) - for c := 1; c <= round.Threshold(); c++ { - z = modQ.Mul(z, kj) - BigXj, err = BigXj.Add(Vc[c].ScalarMult(z)) - if err != nil { - culprits = append(culprits, Pj) - } - } - bigXj[j] = BigXj - } - if len(culprits) > 0 { - return round.WrapError(errors.New("adding Vc[c].ScalarMult(z) to BigXj resulted in a point not on the curve"), culprits...) - } - round.save.BigXj = bigXj - } - - // 18. compute and SAVE the EDDSA public key `y` - eddsaPubKey, err := crypto.NewECPoint(round.Params().EC(), Vc[0].X(), Vc[0].Y()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "public key is not on the curve")) - } - round.save.EDDSAPub = eddsaPubKey - - // PRINT public key & private share - common.Logger.Debugf("%s public key: %x", round.PartyID(), eddsaPubKey) - - round.end <- round.save - return nil -} - -func (round *round3) CanAccept(msg tss.ParsedMessage) bool { - // not expecting any incoming messages in this round - return false -} - -func (round *round3) Update() (bool, *tss.Error) { - // not expecting any incoming messages in this round - return false, nil -} - -func (round *round3) NextRound() tss.Round { - return nil // finished! -} diff --git a/tss-lib/eddsa/keygen/round_fn.go b/tss-lib/eddsa/keygen/round_fn.go new file mode 100644 index 0000000..4a6cb7a --- /dev/null +++ b/tss-lib/eddsa/keygen/round_fn.go @@ -0,0 +1,270 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "bytes" + "errors" + "fmt" + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmts "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// getSSID computes the session ID for domain separation. +func getSSID(params *tss.Parameters, temp *localTempData, roundNumber int) ([]byte, error) { + ssidList := []*big.Int{ + temp.ssidNonce, + big.NewInt(int64(roundNumber)), + big.NewInt(int64(params.PartyCount())), + big.NewInt(int64(params.Threshold())), + } + for _, id := range params.Parties().IDs() { + ssidList = append(ssidList, id.KeyInt()) + } + if id := params.CeremonyID(); len(id) > 0 { + ssidList = append(ssidList, new(big.Int).SetBytes(id)) + } + ssid := common.SHA512_256i(ssidList...) + return ssid.Bytes(), nil +} + +// Round1 generates the VSS polynomial and broadcasts a commitment. +// Returns the keygen state to pass to subsequent rounds. +func Round1(params *tss.Parameters, preParams ...interface{}) (*KeygenState, *RoundOutput, error) { + n := params.PartyCount() + Pi := params.PartyID() + i := Pi.Index + + temp := &localTempData{ + localMessageStore: localMessageStore{ + kgRound1Messages: make([]*tss.Message, n), + kgRound2Message1s: make([]*tss.Message, n), + kgRound2Message2s: make([]*tss.Message, n), + }, + } + save := NewLocalPartySaveData(n) + + temp.ssidNonce = new(big.Int).SetUint64(uint64(params.SSIDNonce())) + ssid, err := getSSID(params, temp, 1) + if err != nil { + return nil, nil, fmt.Errorf("round 1 SSID: %w", err) + } + temp.ssid = ssid + + // Generate partial key share ui. + ui := common.GetRandomPositiveInt(params.PartialKeyRand(), params.EC().Params().N) + temp.ui = ui + + // VSS create. + ids := params.Parties().IDs().Keys() + vs, shares, _, err := vss.Create(params.EC(), params.Threshold(), ui, ids, params.Rand()) + if err != nil { + return nil, nil, fmt.Errorf("round 1 vss create: %w", err) + } + save.Ks = ids + save.ShareID = ids[i] + + temp.vs = vs + temp.shares = shares + + // Commitment. + pGFlat, err := crypto.FlattenECPoints(vs) + if err != nil { + return nil, nil, fmt.Errorf("round 1 flatten: %w", err) + } + cmt := cmts.NewHashCommitment(params.Rand(), pGFlat...) + temp.deCommitPolyG = cmt.D + + r1msg := NewKGRound1Message(Pi, cmt.C) + temp.kgRound1Messages[i] = r1msg + + state := &KeygenState{params: params, save: save, temp: *temp} + return state, &RoundOutput{ + Messages: []*tss.Message{r1msg}, + Poly: vs, + }, nil +} + +// Round2 sends P2P shares and broadcasts decommitment + Schnorr proof. +func Round2(state *KeygenState, r1Msgs []*tss.Message) (*RoundOutput, error) { + params := state.params + temp := &state.temp + n := params.PartyCount() + i := params.PartyID().Index + + // Store r1 commitments. + for j := 0; j < n; j++ { + r1msg := r1Msgs[j].Content.(*KGRound1Message) + if !r1msg.ValidateBasic() { + return nil, tss.NewError(errors.New("invalid round 1 message"), TaskName, 2, params.PartyID(), + r1Msgs[j].From) + } + temp.kgRound1Messages[j] = r1Msgs[j] + } + + // P2P share messages. + msgs := make([]*tss.Message, 0, n) + for j, Pj := range params.Parties().IDs() { + r2msg1 := NewKGRound2Message1(Pj, params.PartyID(), temp.shares[j]) + if j == i { + temp.kgRound2Message1s[j] = r2msg1 + continue + } + temp.kgRound2Message1s[j] = nil // will come from network + msgs = append(msgs, r2msg1) + } + + // Schnorr proof. + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(i))) + pii, err := schnorr.NewZKProof(ContextI, temp.ui, temp.vs[0], params.Rand()) + if err != nil { + return nil, fmt.Errorf("round 2 schnorr proof: %w", err) + } + // Clear ui from memory. + temp.ui = new(big.Int) + + // Broadcast decommitment + proof. + r2msg2 := NewKGRound2Message2(params.PartyID(), temp.deCommitPolyG, pii) + temp.kgRound2Message2s[i] = r2msg2 + msgs = append(msgs, r2msg2) + + return &RoundOutput{Messages: msgs}, nil +} + +// Round3 verifies all decommitments, shares, and Schnorr proofs, +// then computes the distributed EdDSA public key and saves the result. +func Round3(state *KeygenState, r2p2p, r2bcast []*tss.Message) (*RoundOutput, error) { + params := state.params + temp := &state.temp + save := &state.save + n := params.PartyCount() + PIdx := params.PartyID().Index + + // Compute own Xi from shares. + xi := new(big.Int).Set(temp.shares[PIdx].Share) + for j := 0; j < n; j++ { + if j == PIdx { + continue + } + r2msg1 := r2p2p[j].Content.(*KGRound2Message1) + xi = new(big.Int).Add(xi, r2msg1.Share) + } + save.Xi = new(big.Int).Mod(xi, params.EC().Params().N) + if save.Xi.Sign() == 0 { + return nil, tss.NewError(errors.New("xi is zero"), TaskName, 3, params.PartyID()) + } + + // Verify each party's decommitment, Schnorr proof, and VSS share. + Vc := make(vss.Vs, params.Threshold()+1) + for c := range Vc { + Vc[c] = temp.vs[c] + } + + for j := 0; j < n; j++ { + if j == PIdx { + continue + } + Pj := params.Parties().IDs()[j] + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + + // Verify commitment. + r1msg := r1MsgContent(state, j) + r2msg2 := r2bcast[j].Content.(*KGRound2Message2) + cmtDeCmt := cmts.HashCommitDecommit{C: r1msg.Commitment, D: r2msg2.DeCommitment} + ok, flatPolyGs := cmtDeCmt.DeCommit() + if !ok || flatPolyGs == nil { + return nil, tss.NewError(errors.New("de-commitment verify failed"), TaskName, 3, params.PartyID(), Pj) + } + PjVs, err := crypto.UnFlattenECPoints(params.EC(), flatPolyGs) + if err != nil { + return nil, tss.NewError(fmt.Errorf("unflatten: %w", err), TaskName, 3, params.PartyID(), Pj) + } + // Cofactor clearing for Edwards curve — rejects torsion points. + for k := range PjVs { + PjVs[k] = PjVs[k].EightInvEight() + } + + // Schnorr proof verify. + if r2msg2.ZKProof == nil { + return nil, tss.NewError(errors.New("missing schnorr proof"), TaskName, 3, params.PartyID(), Pj) + } + if !r2msg2.ZKProof.Verify(ContextJ, PjVs[0]) { + return nil, tss.NewError(errors.New("schnorr proof verify failed"), TaskName, 3, params.PartyID(), Pj) + } + + // Receiver binding check. + r2msg1 := r2p2p[j].Content.(*KGRound2Message1) + if !bytes.Equal(r2msg1.ReceiverID, params.PartyID().Key) { + return nil, tss.NewError(errors.New("receiverId mismatch"), TaskName, 3, params.PartyID(), Pj) + } + + // VSS share verify. + PjShare := vss.Share{ + Threshold: params.Threshold(), + ID: params.PartyID().KeyInt(), + Share: r2msg1.Share, + } + if !PjShare.Verify(params.EC(), params.Threshold(), PjVs) { + return nil, tss.NewError(errors.New("vss share verify failed"), TaskName, 3, params.PartyID(), Pj) + } + + // Accumulate Vc. + for c := 0; c <= params.Threshold(); c++ { + var err error + Vc[c], err = Vc[c].Add(PjVs[c]) + if err != nil { + return nil, tss.NewError(fmt.Errorf("vc point addition failed"), TaskName, 3, params.PartyID(), Pj) + } + } + } + + // Compute BigXj for each party. + modQ := common.ModInt(params.EC().Params().N) + for j := 0; j < n; j++ { + Pj := params.Parties().IDs()[j] + kj := Pj.KeyInt() + BigXj := Vc[0] + z := new(big.Int).SetInt64(1) + for c := 1; c <= params.Threshold(); c++ { + z = modQ.Mul(z, kj) + var err error + BigXj, err = BigXj.Add(Vc[c].ScalarMult(z)) + if err != nil { + return nil, tss.NewError(errors.New("BigXj computation failed"), TaskName, 3, params.PartyID(), Pj) + } + } + if BigXj.IsIdentity() { + return nil, tss.NewError(errors.New("BigXj is the identity point"), TaskName, 3, params.PartyID(), Pj) + } + save.BigXj[j] = BigXj + } + + // Compute EdDSA public key. + eddsaPubKey, err := crypto.NewECPoint(params.EC(), Vc[0].X(), Vc[0].Y()) + if err != nil { + return nil, fmt.Errorf("public key not on curve: %w", err) + } + if eddsaPubKey.IsIdentity() { + return nil, tss.NewError(errors.New("public key is the identity point"), TaskName, 3, params.PartyID()) + } + save.EDDSAPub = eddsaPubKey + + return &RoundOutput{Save: save}, nil +} + +// r1MsgContent extracts the KGRound1Message from the keygen state's +// stored round 1 messages. For the party's own message, it reads from +// the state; for others, from the passed-in r1Msgs via Round1. +// This helper keeps Round3 clean. +func r1MsgContent(state *KeygenState, j int) *KGRound1Message { + return state.temp.kgRound1Messages[j].Content.(*KGRound1Message) +} diff --git a/tss-lib/eddsa/keygen/round_fn_test.go b/tss-lib/eddsa/keygen/round_fn_test.go new file mode 100644 index 0000000..8f8b9aa --- /dev/null +++ b/tss-lib/eddsa/keygen/round_fn_test.go @@ -0,0 +1,77 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "testing" + + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestRoundFnEdDSAKeygenThreeParties(t *testing.T) { + const n = 3 + const threshold = 1 + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + // --- Round 1 --- + states := make([]*KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := Round1(params) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + if out.Poly == nil { + t.Fatal("Round1 should return Poly") + } + } + + // --- Round 2 --- + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := Round2(states[i], r1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + // --- Round 3 --- + for i := 0; i < n; i++ { + out, err := Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("Round3[%d]: %v", i, err) + } + if out.Save == nil { + t.Fatal("Round3 should return Save") + } + if err := out.Save.ValidateSaveData(); err != nil { + t.Fatalf("ValidateSaveData[%d]: %v", i, err) + } + t.Logf("party %d: EDDSAPub = (%x, %x)", i, + out.Save.EDDSAPub.X(), out.Save.EDDSAPub.Y()) + } +} diff --git a/tss-lib/eddsa/keygen/round_state.go b/tss-lib/eddsa/keygen/round_state.go new file mode 100644 index 0000000..c7e4466 --- /dev/null +++ b/tss-lib/eddsa/keygen/round_state.go @@ -0,0 +1,39 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// KeygenState holds mutable state across all keygen rounds for one party. +type KeygenState struct { + params *tss.Parameters + save LocalPartySaveData + temp localTempData +} + +// RoundOutput is returned by each round function. +type RoundOutput struct { + // Messages to send to other parties. + Messages []*tss.Message + // Save is non-nil only after the final round. + Save *LocalPartySaveData + // Poly is the VSS polynomial (available after Round1 for SNARK witness). + Poly vss.Vs +} + +// ExportR2P2PSelf returns the party's own P2P Round 2 message. +func (s *KeygenState) ExportR2P2PSelf() *tss.Message { + i := s.params.PartyID().Index + return s.temp.kgRound2Message1s[i] +} + +// ExportR2BcastSelf returns the party's own broadcast Round 2 message. +func (s *KeygenState) ExportR2BcastSelf() *tss.Message { + i := s.params.PartyID().Index + return s.temp.kgRound2Message2s[i] +} diff --git a/tss-lib/eddsa/keygen/rounds.go b/tss-lib/eddsa/keygen/rounds.go deleted file mode 100644 index 54c4ae0..0000000 --- a/tss-lib/eddsa/keygen/rounds.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - TaskName = "eddsa-keygen" -) - -type ( - base struct { - *tss.Parameters - save *LocalPartySaveData - temp *localTempData - out chan<- tss.Message - end chan<- *LocalPartySaveData - ok []bool // `ok` tracks parties which have been verified by Update() - started bool - number int - } - round1 struct { - *base - } - round2 struct { - *round1 - } - round3 struct { - *round2 - } -) - -func (round *base) Params() *tss.Parameters { - return round.Parameters -} - -func (round *base) RoundNumber() int { - return round.number -} - -// CanProceed is inherited by other rounds -func (round *base) CanProceed() bool { - if !round.started { - return false - } - for _, ok := range round.ok { - if !ok { - return false - } - } - return true -} - -// WaitingFor is called by a Party for reporting back to the caller -func (round *base) WaitingFor() []*tss.PartyID { - Ps := round.Parties().IDs() - ids := make([]*tss.PartyID, 0, len(round.ok)) - for j, ok := range round.ok { - if ok { - continue - } - ids = append(ids, Ps[j]) - } - return ids -} - -func (round *base) WrapError(err error, culprits ...*tss.PartyID) *tss.Error { - return tss.NewError(err, TaskName, round.number, round.PartyID(), culprits...) -} - -// ----- // - -// `ok` tracks parties which have been verified by Update() -func (round *base) resetOK() { - for j := range round.ok { - round.ok[j] = false - } -} - -// get ssid from local params -func (round *base) getSSID() ([]byte, error) { - ssidList := []*big.Int{round.EC().Params().P, round.EC().Params().N, round.EC().Params().Gx, round.EC().Params().Gy} // ec curve - ssidList = append(ssidList, round.Parties().IDs().Keys()...) - ssidList = append(ssidList, big.NewInt(int64(round.number))) // round number - ssidList = append(ssidList, round.temp.ssidNonce) - ssid := common.SHA512_256i(ssidList...).Bytes() - - return ssid, nil -} diff --git a/tss-lib/eddsa/keygen/save_data.go b/tss-lib/eddsa/keygen/save_data.go index b269c64..e5dfe33 100644 --- a/tss-lib/eddsa/keygen/save_data.go +++ b/tss-lib/eddsa/keygen/save_data.go @@ -1,47 +1,69 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package keygen import ( "encoding/hex" - "math/big" + "errors" + "fmt" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -type ( - LocalSecrets struct { - // secret fields (not shared, but stored locally) - Xi, ShareID *big.Int // xi, kj +// ValidateSaveData checks that the saved keygen data is consistent +// and usable for signing or resharing. +func (saveData LocalPartySaveData) ValidateSaveData() error { + if saveData.Xi == nil || saveData.ShareID == nil { + return errors.New("ValidateSaveData: Xi or ShareID is nil") } - - // Everything in LocalPartySaveData is saved locally to user's HD when done - LocalPartySaveData struct { - LocalSecrets - - // original indexes (ki in signing preparation phase) - Ks []*big.Int - - // public keys (Xj = uj*G for each Pj) - BigXj []*crypto.ECPoint // Xj - - // used for test assertions (may be discarded) - EDDSAPub *crypto.ECPoint // y + if saveData.EDDSAPub == nil { + return errors.New("ValidateSaveData: EDDSAPub is nil") } -) - -func NewLocalPartySaveData(partyCount int) (saveData LocalPartySaveData) { - saveData.Ks = make([]*big.Int, partyCount) - saveData.BigXj = make([]*crypto.ECPoint, partyCount) - return + n := len(saveData.Ks) + if n < 2 { + return fmt.Errorf("ValidateSaveData: party count %d is less than 2", n) + } + if len(saveData.BigXj) != n { + return errors.New("ValidateSaveData: BigXj length does not match Ks") + } + for i := 0; i < n; i++ { + if saveData.Ks[i] == nil { + return fmt.Errorf("ValidateSaveData: Ks[%d] is nil", i) + } + if saveData.BigXj[i] == nil { + return fmt.Errorf("ValidateSaveData: BigXj[%d] is nil", i) + } + if !saveData.BigXj[i].IsOnCurve() { + return fmt.Errorf("ValidateSaveData: BigXj[%d] is not on curve", i) + } + } + ownIdx := -1 + for i, k := range saveData.Ks { + if k.Cmp(saveData.ShareID) == 0 { + ownIdx = i + break + } + } + if ownIdx == -1 { + return errors.New("ValidateSaveData: ShareID not found in Ks") + } + if saveData.Xi.Sign() == 0 { + return errors.New("ValidateSaveData: Xi is zero") + } + ec := saveData.BigXj[ownIdx].Curve() + xiG := crypto.ScalarBaseMult(ec, saveData.Xi) + if !xiG.Equals(saveData.BigXj[ownIdx]) { + return errors.New("ValidateSaveData: Feldman VSS check failed: Xi·G != BigXj[ownIndex]") + } + return nil } -// BuildLocalSaveDataSubset re-creates the LocalPartySaveData to contain data for only the list of signing parties. +// BuildLocalSaveDataSubset re-creates the LocalPartySaveData for only +// the given signing parties. func BuildLocalSaveDataSubset(sourceData LocalPartySaveData, sortedIDs tss.SortedPartyIDs) LocalPartySaveData { keysToIndices := make(map[string]int, len(sourceData.Ks)) for j, kj := range sourceData.Ks { diff --git a/tss-lib/eddsa/keygen/test_utils.go b/tss-lib/eddsa/keygen/test_utils.go deleted file mode 100644 index f0060af..0000000 --- a/tss-lib/eddsa/keygen/test_utils.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package keygen - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "math/rand" - "path/filepath" - "runtime" - "sort" - - "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - // To change these parameters, you must first delete the text fixture files in test/_fixtures/ and then run the keygen test alone. - // Then the signing and resharing tests will work with the new n, t configuration using the newly written fixture files. - TestParticipants = test.TestParticipants - TestThreshold = test.TestParticipants / 2 -) -const ( - testFixtureDirFormat = "%s/../../test/_eddsa_fixtures" - testFixtureFileFormat = "keygen_data_%d.json" -) - -func LoadKeygenTestFixtures(qty int, optionalStart ...int) ([]LocalPartySaveData, tss.SortedPartyIDs, error) { - keys := make([]LocalPartySaveData, 0, qty) - start := 0 - if 0 < len(optionalStart) { - start = optionalStart[0] - } - for i := start; i < qty; i++ { - fixtureFilePath := makeTestFixtureFilePath(i) - bz, err := ioutil.ReadFile(fixtureFilePath) - if err != nil { - return nil, nil, errors.Wrapf(err, - "could not open the test fixture for party %d in the expected location: %s. run keygen tests first.", - i, fixtureFilePath) - } - var key LocalPartySaveData - if err = json.Unmarshal(bz, &key); err != nil { - return nil, nil, errors.Wrapf(err, - "could not unmarshal fixture data for party %d located at: %s", - i, fixtureFilePath) - } - for _, kbxj := range key.BigXj { - kbxj.SetCurve(tss.Edwards()) - } - key.EDDSAPub.SetCurve(tss.Edwards()) - keys = append(keys, key) - } - partyIDs := make(tss.UnSortedPartyIDs, len(keys)) - for i, key := range keys { - pMoniker := fmt.Sprintf("%d", i+start+1) - partyIDs[i] = tss.NewPartyID(pMoniker, pMoniker, key.ShareID) - } - sortedPIDs := tss.SortPartyIDs(partyIDs) - return keys, sortedPIDs, nil -} - -func LoadKeygenTestFixturesRandomSet(qty, fixtureCount int) ([]LocalPartySaveData, tss.SortedPartyIDs, error) { - keys := make([]LocalPartySaveData, 0, qty) - plucked := make(map[int]interface{}, qty) - for i := 0; len(plucked) < qty; i = (i + 1) % fixtureCount { - _, have := plucked[i] - if pluck := rand.Float32() < 0.5; !have && pluck { - plucked[i] = new(struct{}) - } - } - for i := range plucked { - fixtureFilePath := makeTestFixtureFilePath(i) - bz, err := ioutil.ReadFile(fixtureFilePath) - if err != nil { - return nil, nil, errors.Wrapf(err, - "could not open the test fixture for party %d in the expected location: %s. run keygen tests first.", - i, fixtureFilePath) - } - var key LocalPartySaveData - if err = json.Unmarshal(bz, &key); err != nil { - return nil, nil, errors.Wrapf(err, - "could not unmarshal fixture data for party %d located at: %s", - i, fixtureFilePath) - } - for _, kbxj := range key.BigXj { - kbxj.SetCurve(tss.Edwards()) - } - key.EDDSAPub.SetCurve(tss.Edwards()) - keys = append(keys, key) - } - partyIDs := make(tss.UnSortedPartyIDs, len(keys)) - j := 0 - for i := range plucked { - key := keys[j] - pMoniker := fmt.Sprintf("%d", i+1) - partyIDs[j] = tss.NewPartyID(pMoniker, pMoniker, key.ShareID) - j++ - } - sortedPIDs := tss.SortPartyIDs(partyIDs) - sort.Slice(keys, func(i, j int) bool { return keys[i].ShareID.Cmp(keys[j].ShareID) == -1 }) - return keys, sortedPIDs, nil -} - -func makeTestFixtureFilePath(partyIndex int) string { - _, callerFileName, _, _ := runtime.Caller(0) - srcDirName := filepath.Dir(callerFileName) - fixtureDirName := fmt.Sprintf(testFixtureDirFormat, srcDirName) - return fmt.Sprintf("%s/"+testFixtureFileFormat, fixtureDirName, partyIndex) -} diff --git a/tss-lib/eddsa/keygen/types.go b/tss-lib/eddsa/keygen/types.go new file mode 100644 index 0000000..978c0d9 --- /dev/null +++ b/tss-lib/eddsa/keygen/types.go @@ -0,0 +1,59 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TaskName identifies the EdDSA keygen protocol in error messages. +const TaskName = "eddsa-keygen" + +type localTempData struct { + localMessageStore + + ssidNonce *big.Int + ssid []byte + + // round 1 data + ui *big.Int + vs vss.Vs + shares vss.Shares + + deCommitPolyG []*big.Int +} + +type localMessageStore struct { + kgRound1Messages []*tss.Message + kgRound2Message1s []*tss.Message + kgRound2Message2s []*tss.Message +} + +// LocalSecrets holds the party's secret key material. +type LocalSecrets struct { + Xi, ShareID *big.Int +} + +// LocalPartySaveData holds the complete keygen output for one party. +type LocalPartySaveData struct { + LocalSecrets + + Ks []*big.Int + BigXj []*crypto.ECPoint + // EDDSAPub is the distributed EdDSA public key. + EDDSAPub *crypto.ECPoint +} + +// NewLocalPartySaveData allocates a LocalPartySaveData with slices sized for partyCount. +func NewLocalPartySaveData(partyCount int) (saveData LocalPartySaveData) { + saveData.Ks = make([]*big.Int, partyCount) + saveData.BigXj = make([]*crypto.ECPoint, partyCount) + return +} diff --git a/tss-lib/eddsa/keygen/validate_test.go b/tss-lib/eddsa/keygen/validate_test.go new file mode 100644 index 0000000..0b10ea1 --- /dev/null +++ b/tss-lib/eddsa/keygen/validate_test.go @@ -0,0 +1,184 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package keygen + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// --- ValidateBasic --- + +func TestKGRound1MessageValidateBasic(t *testing.T) { + if (&KGRound1Message{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + if (&KGRound1Message{Commitment: big.NewInt(0)}).ValidateBasic() { + t.Fatal("zero commitment should fail") + } + if (*KGRound1Message)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if !(&KGRound1Message{Commitment: big.NewInt(42)}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestKGRound2Message1ValidateBasic(t *testing.T) { + if (*KGRound2Message1)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&KGRound2Message1{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + if (&KGRound2Message1{Share: big.NewInt(1)}).ValidateBasic() { + t.Fatal("missing ReceiverID should fail") + } + if !(&KGRound2Message1{Share: big.NewInt(1), ReceiverID: []byte("x")}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestKGRound2Message2ValidateBasic(t *testing.T) { + ec := tss.Edwards() + alpha := crypto.ScalarBaseMult(ec, big.NewInt(7)) + proof := &schnorr.ZKProof{Alpha: alpha, T: big.NewInt(99)} + + if (*KGRound2Message2)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&KGRound2Message2{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + if (&KGRound2Message2{DeCommitment: cmt.HashDeCommitment{big.NewInt(1)}}).ValidateBasic() { + t.Fatal("short decommitment should fail") + } + if !(&KGRound2Message2{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: proof, + }).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +// --- SaveData --- + +func TestValidateSaveDataNilFields(t *testing.T) { + sd := LocalPartySaveData{} + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("empty save data should fail") + } +} + +func TestValidateSaveDataTooFewParties(t *testing.T) { + ec := tss.Edwards() + pt := crypto.ScalarBaseMult(ec, big.NewInt(42)) + sd := LocalPartySaveData{ + LocalSecrets: LocalSecrets{Xi: big.NewInt(1), ShareID: big.NewInt(1)}, + EDDSAPub: pt, + Ks: []*big.Int{big.NewInt(1)}, // < 2 + BigXj: []*crypto.ECPoint{pt}, + } + if err := sd.ValidateSaveData(); err == nil { + t.Fatal("party count < 2 should fail") + } +} + +func TestBuildLocalSaveDataSubset(t *testing.T) { + // Run a keygen to get real save data, then test subset + const n = 3 + const threshold = 1 + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states := make([]*KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := Round1(params) + if err != nil { + t.Fatalf("Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := Round2(states[i], r1) + if err != nil { + t.Fatalf("Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + var fullSave *LocalPartySaveData + for i := 0; i < n; i++ { + out, err := Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("Round3[%d]: %v", i, err) + } + if i == 0 { + fullSave = out.Save + } + } + + // Take subset of 2 parties + subset := tss.SortPartyIDs(tss.UnSortedPartyIDs{pIDs[0], pIDs[1]}) + subData := BuildLocalSaveDataSubset(*fullSave, subset) + if len(subData.Ks) != 2 { + t.Fatalf("subset Ks: want 2, got %d", len(subData.Ks)) + } + if subData.EDDSAPub == nil { + t.Fatal("subset should preserve EDDSAPub") + } +} + +// --- ExportR2BcastSelf --- + +func TestExportR2BcastSelf(t *testing.T) { + pIDs := tss.GenerateTestPartyIDs(3) + peerCtx := tss.NewPeerContext(pIDs) + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[0], 3, 1) + st, _, err := Round1(params) + if err != nil { + t.Fatal(err) + } + r1 := make([]*tss.Message, 3) + for i := 0; i < 3; i++ { + p := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], 3, 1) + _, out, err := Round1(p) + if err != nil { + t.Fatal(err) + } + r1[i] = out.Messages[0] + } + if _, err := Round2(st, r1); err != nil { + t.Fatal(err) + } + bcast := st.ExportR2BcastSelf() + if bcast == nil { + t.Fatal("ExportR2BcastSelf returned nil") + } +} diff --git a/tss-lib/eddsa/resharing/eddsa-resharing.pb.go b/tss-lib/eddsa/resharing/eddsa-resharing.pb.go deleted file mode 100644 index 25c33ed..0000000 --- a/tss-lib/eddsa/resharing/eddsa-resharing.pb.go +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.14.0 -// source: protob/eddsa-resharing.proto - -package resharing - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// -// The Round 1 data is broadcast to peers of the New Committee in this message. -type DGRound1Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - EddsaPubX []byte `protobuf:"bytes,1,opt,name=eddsa_pub_x,json=eddsaPubX,proto3" json:"eddsa_pub_x,omitempty"` - EddsaPubY []byte `protobuf:"bytes,2,opt,name=eddsa_pub_y,json=eddsaPubY,proto3" json:"eddsa_pub_y,omitempty"` - VCommitment []byte `protobuf:"bytes,3,opt,name=v_commitment,json=vCommitment,proto3" json:"v_commitment,omitempty"` -} - -func (x *DGRound1Message) Reset() { - *x = DGRound1Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_resharing_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound1Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound1Message) ProtoMessage() {} - -func (x *DGRound1Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_resharing_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound1Message.ProtoReflect.Descriptor instead. -func (*DGRound1Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_resharing_proto_rawDescGZIP(), []int{0} -} - -func (x *DGRound1Message) GetEddsaPubX() []byte { - if x != nil { - return x.EddsaPubX - } - return nil -} - -func (x *DGRound1Message) GetEddsaPubY() []byte { - if x != nil { - return x.EddsaPubY - } - return nil -} - -func (x *DGRound1Message) GetVCommitment() []byte { - if x != nil { - return x.VCommitment - } - return nil -} - -// -// The Round 2 "ACK" is broadcast to peers of the Old Committee in this message. -type DGRound2Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DGRound2Message) Reset() { - *x = DGRound2Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_resharing_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound2Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound2Message) ProtoMessage() {} - -func (x *DGRound2Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_resharing_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound2Message.ProtoReflect.Descriptor instead. -func (*DGRound2Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_resharing_proto_rawDescGZIP(), []int{1} -} - -// -// The Round 3 data is sent to peers of the New Committee in this message. -type DGRound3Message1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Share []byte `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"` -} - -func (x *DGRound3Message1) Reset() { - *x = DGRound3Message1{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_resharing_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound3Message1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound3Message1) ProtoMessage() {} - -func (x *DGRound3Message1) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_resharing_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound3Message1.ProtoReflect.Descriptor instead. -func (*DGRound3Message1) Descriptor() ([]byte, []int) { - return file_protob_eddsa_resharing_proto_rawDescGZIP(), []int{2} -} - -func (x *DGRound3Message1) GetShare() []byte { - if x != nil { - return x.Share - } - return nil -} - -// -// The Round 3 data is broadcast to peers of the New Committee in this message. -type DGRound3Message2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - VDecommitment [][]byte `protobuf:"bytes,1,rep,name=v_decommitment,json=vDecommitment,proto3" json:"v_decommitment,omitempty"` -} - -func (x *DGRound3Message2) Reset() { - *x = DGRound3Message2{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_resharing_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound3Message2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound3Message2) ProtoMessage() {} - -func (x *DGRound3Message2) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_resharing_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound3Message2.ProtoReflect.Descriptor instead. -func (*DGRound3Message2) Descriptor() ([]byte, []int) { - return file_protob_eddsa_resharing_proto_rawDescGZIP(), []int{3} -} - -func (x *DGRound3Message2) GetVDecommitment() [][]byte { - if x != nil { - return x.VDecommitment - } - return nil -} - -// -// The Round 4 "ACK" is broadcast to peers of the Old and New Committees from the New Committee in this message. -type DGRound4Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DGRound4Message) Reset() { - *x = DGRound4Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_resharing_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DGRound4Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DGRound4Message) ProtoMessage() {} - -func (x *DGRound4Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_resharing_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DGRound4Message.ProtoReflect.Descriptor instead. -func (*DGRound4Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_resharing_proto_rawDescGZIP(), []int{4} -} - -var File_protob_eddsa_resharing_proto protoreflect.FileDescriptor - -var file_protob_eddsa_resharing_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x65, 0x64, 0x64, 0x73, 0x61, 0x2d, 0x72, - 0x65, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, - 0x62, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x65, - 0x64, 0x64, 0x73, 0x61, 0x2e, 0x72, 0x65, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x74, - 0x0a, 0x0f, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x65, 0x64, 0x64, 0x73, 0x61, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x78, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x64, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, - 0x58, 0x12, 0x1e, 0x0a, 0x0b, 0x65, 0x64, 0x64, 0x73, 0x61, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x64, 0x64, 0x73, 0x61, 0x50, 0x75, 0x62, - 0x59, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x11, 0x0a, 0x0f, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x28, 0x0a, 0x10, 0x44, 0x47, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x33, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x73, - 0x68, 0x61, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x22, 0x39, 0x0a, 0x10, 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x32, 0x12, 0x25, 0x0a, 0x0e, 0x76, 0x5f, 0x64, 0x65, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0d, 0x76, - 0x44, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x11, 0x0a, 0x0f, - 0x44, 0x47, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x34, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, - 0x11, 0x5a, 0x0f, 0x65, 0x64, 0x64, 0x73, 0x61, 0x2f, 0x72, 0x65, 0x73, 0x68, 0x61, 0x72, 0x69, - 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_protob_eddsa_resharing_proto_rawDescOnce sync.Once - file_protob_eddsa_resharing_proto_rawDescData = file_protob_eddsa_resharing_proto_rawDesc -) - -func file_protob_eddsa_resharing_proto_rawDescGZIP() []byte { - file_protob_eddsa_resharing_proto_rawDescOnce.Do(func() { - file_protob_eddsa_resharing_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_eddsa_resharing_proto_rawDescData) - }) - return file_protob_eddsa_resharing_proto_rawDescData -} - -var file_protob_eddsa_resharing_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_protob_eddsa_resharing_proto_goTypes = []interface{}{ - (*DGRound1Message)(nil), // 0: binance.tsslib.eddsa.resharing.DGRound1Message - (*DGRound2Message)(nil), // 1: binance.tsslib.eddsa.resharing.DGRound2Message - (*DGRound3Message1)(nil), // 2: binance.tsslib.eddsa.resharing.DGRound3Message1 - (*DGRound3Message2)(nil), // 3: binance.tsslib.eddsa.resharing.DGRound3Message2 - (*DGRound4Message)(nil), // 4: binance.tsslib.eddsa.resharing.DGRound4Message -} -var file_protob_eddsa_resharing_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_protob_eddsa_resharing_proto_init() } -func file_protob_eddsa_resharing_proto_init() { - if File_protob_eddsa_resharing_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_eddsa_resharing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound1Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_resharing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound2Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_resharing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound3Message1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_resharing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound3Message2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_resharing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DGRound4Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_eddsa_resharing_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_eddsa_resharing_proto_goTypes, - DependencyIndexes: file_protob_eddsa_resharing_proto_depIdxs, - MessageInfos: file_protob_eddsa_resharing_proto_msgTypes, - }.Build() - File_protob_eddsa_resharing_proto = out.File - file_protob_eddsa_resharing_proto_rawDesc = nil - file_protob_eddsa_resharing_proto_goTypes = nil - file_protob_eddsa_resharing_proto_depIdxs = nil -} diff --git a/tss-lib/eddsa/resharing/local_party.go b/tss-lib/eddsa/resharing/local_party.go deleted file mode 100644 index 4f28785..0000000 --- a/tss-lib/eddsa/resharing/local_party.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Implements Party -// Implements Stringer -var _ tss.Party = (*LocalParty)(nil) -var _ fmt.Stringer = (*LocalParty)(nil) - -type ( - LocalParty struct { - *tss.BaseParty - params *tss.ReSharingParameters - - temp localTempData - input, save keygen.LocalPartySaveData - - // outbound messaging - out chan<- tss.Message - end chan<- *keygen.LocalPartySaveData - } - - localMessageStore struct { - dgRound1Messages, - dgRound2Messages, - dgRound3Message1s, - dgRound3Message2s, - dgRound4Messages []tss.ParsedMessage - } - - localTempData struct { - localMessageStore - - // temp data (thrown away after rounds) - NewVs vss.Vs - NewShares vss.Shares - VD cmt.HashDeCommitment - - // temporary storage of data that is persisted by the new party in round 5 if all "ACK" messages are received - newXi *big.Int - newKs []*big.Int - newBigXjs []*crypto.ECPoint // Xj to save in round 5 - } -) - -// Exported, used in `tss` client -// The `key` is read from and/or written to depending on whether this party is part of the old or the new committee. -// You may optionally generate and set the LocalPreParams if you would like to use pre-generated safe primes and Paillier secret. -// (This is similar to providing the `optionalPreParams` to `keygen.LocalParty`). -func NewLocalParty( - params *tss.ReSharingParameters, - key keygen.LocalPartySaveData, - out chan<- tss.Message, - end chan<- *keygen.LocalPartySaveData, -) tss.Party { - oldPartyCount := len(params.OldParties().IDs()) - subset := key - if params.IsOldCommittee() { - subset = keygen.BuildLocalSaveDataSubset(key, params.OldParties().IDs()) - } - p := &LocalParty{ - BaseParty: new(tss.BaseParty), - params: params, - temp: localTempData{}, - input: subset, - save: keygen.NewLocalPartySaveData(params.NewPartyCount()), - out: out, - end: end, - } - // msgs init - p.temp.dgRound1Messages = make([]tss.ParsedMessage, oldPartyCount) // from t+1 of Old Committee - p.temp.dgRound2Messages = make([]tss.ParsedMessage, params.NewPartyCount()) // from n of New Committee - p.temp.dgRound3Message1s = make([]tss.ParsedMessage, oldPartyCount) // from t+1 of Old Committee - p.temp.dgRound3Message2s = make([]tss.ParsedMessage, oldPartyCount) // " - p.temp.dgRound4Messages = make([]tss.ParsedMessage, params.NewPartyCount()) // from n of New Committee - - return p -} - -func (p *LocalParty) FirstRound() tss.Round { - return newRound1(p.params, &p.input, &p.save, &p.temp, p.out, p.end) -} - -func (p *LocalParty) Start() *tss.Error { - return tss.BaseStart(p, TaskName) -} - -func (p *LocalParty) Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) { - return tss.BaseUpdate(p, msg, TaskName) -} - -func (p *LocalParty) UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (bool, *tss.Error) { - msg, err := tss.ParseWireMessage(wireBytes, from, isBroadcast) - if err != nil { - return false, p.WrapError(err) - } - return p.Update(msg) -} - -func (p *LocalParty) ValidateMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - if ok, err := p.BaseParty.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - // check that the message's "from index" will fit into the array - var maxFromIdx int - switch msg.Content().(type) { - case *DGRound2Message, *DGRound4Message: - maxFromIdx = len(p.params.NewParties().IDs()) - 1 - default: - maxFromIdx = len(p.params.OldParties().IDs()) - 1 - } - if maxFromIdx < msg.GetFrom().Index { - return false, p.WrapError(fmt.Errorf("received msg with a sender index too great (%d <= %d)", - maxFromIdx, msg.GetFrom().Index), msg.GetFrom()) - } - return true, nil -} - -func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - // ValidateBasic is cheap; double-check the message here in case the public StoreMessage was called externally - if ok, err := p.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - fromPIdx := msg.GetFrom().Index - - // switch/case is necessary to store any messages beyond current round - // this does not handle message replays. we expect the caller to apply replay and spoofing protection. - switch msg.Content().(type) { - case *DGRound1Message: - p.temp.dgRound1Messages[fromPIdx] = msg - case *DGRound2Message: - p.temp.dgRound2Messages[fromPIdx] = msg - case *DGRound3Message1: - p.temp.dgRound3Message1s[fromPIdx] = msg - case *DGRound3Message2: - p.temp.dgRound3Message2s[fromPIdx] = msg - case *DGRound4Message: - p.temp.dgRound4Messages[fromPIdx] = msg - default: // unrecognised message, just ignore! - common.Logger.Warningf("unrecognised message ignored: %v", msg) - return false, nil - } - return true, nil -} - -func (p *LocalParty) PartyID() *tss.PartyID { - return p.params.PartyID() -} - -func (p *LocalParty) String() string { - return fmt.Sprintf("id: %s, %s", p.PartyID(), p.BaseParty.String()) -} diff --git a/tss-lib/eddsa/resharing/local_party_test.go b/tss-lib/eddsa/resharing/local_party_test.go deleted file mode 100644 index c2e27f1..0000000 --- a/tss-lib/eddsa/resharing/local_party_test.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing_test - -import ( - "math/big" - "sync/atomic" - "testing" - - "github.com/decred/dcrd/dcrec/edwards/v2" - "github.com/ipfs/go-log" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - . "github.com/hemilabs/x/tss-lib/v2/eddsa/resharing" - "github.com/hemilabs/x/tss-lib/v2/eddsa/signing" - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - testParticipants = test.TestParticipants - testThreshold = test.TestThreshold -) - -func setUp(level string) { - if err := log.SetLogLevel("tss-lib", level); err != nil { - panic(err) - } - - // only for test - tss.SetCurve(tss.Edwards()) -} - -func TestE2EConcurrent(t *testing.T) { - setUp("info") - - threshold, newThreshold := testThreshold, testThreshold - - // PHASE: load keygen fixtures - firstPartyIdx, extraParties := 1, 1 // // extra can be 0 to N-first - oldKeys, oldPIDs, err := keygen.LoadKeygenTestFixtures(testThreshold+1+extraParties+firstPartyIdx, firstPartyIdx) - assert.NoError(t, err, "should load keygen fixtures") - - // PHASE: resharing - oldP2PCtx := tss.NewPeerContext(oldPIDs) - - // init the new parties; re-use the fixture pre-params for speed - newPIDs := tss.GenerateTestPartyIDs(testParticipants) - newP2PCtx := tss.NewPeerContext(newPIDs) - newPCount := len(newPIDs) - - oldCommittee := make([]*LocalParty, 0, len(oldPIDs)) - newCommittee := make([]*LocalParty, 0, newPCount) - bothCommitteesPax := len(oldCommittee) + len(newCommittee) - - errCh := make(chan *tss.Error, bothCommitteesPax) - outCh := make(chan tss.Message, bothCommitteesPax) - endCh := make(chan *keygen.LocalPartySaveData, bothCommitteesPax) - - updater := test.SharedPartyUpdater - - // init the old parties first - for j, pID := range oldPIDs { - params := tss.NewReSharingParameters(tss.Edwards(), oldP2PCtx, newP2PCtx, pID, testParticipants, threshold, newPCount, newThreshold) - P := NewLocalParty(params, oldKeys[j], outCh, endCh).(*LocalParty) // discard old key data - oldCommittee = append(oldCommittee, P) - } - - // init the new parties - for _, pID := range newPIDs { - params := tss.NewReSharingParameters(tss.Edwards(), oldP2PCtx, newP2PCtx, pID, testParticipants, threshold, newPCount, newThreshold) - save := keygen.NewLocalPartySaveData(newPCount) - P := NewLocalParty(params, save, outCh, endCh).(*LocalParty) - newCommittee = append(newCommittee, P) - } - - // start the new parties; they will wait for messages - for _, P := range newCommittee { - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - // start the old parties; they will send messages - for _, P := range oldCommittee { - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - newKeys := make([]keygen.LocalPartySaveData, len(newCommittee)) - endedOldCommittee := 0 - var reSharingEnded int32 - for { - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - return - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - t.Fatal("did not expect a msg to have a nil destination during resharing") - } - if msg.IsToOldCommittee() || msg.IsToOldAndNewCommittees() { - for _, destP := range dest[:len(oldCommittee)] { - go updater(oldCommittee[destP.Index], msg, errCh) - } - } - if !msg.IsToOldCommittee() || msg.IsToOldAndNewCommittees() { - for _, destP := range dest { - go updater(newCommittee[destP.Index], msg, errCh) - } - } - - case save := <-endCh: - // old committee members that aren't receiving a share have their Xi zeroed - if save.Xi != nil { - index, err := save.OriginalIndex() - assert.NoErrorf(t, err, "should not be an error getting a party's index from save data") - newKeys[index] = *save - } else { - endedOldCommittee++ - } - atomic.AddInt32(&reSharingEnded, 1) - if atomic.LoadInt32(&reSharingEnded) == int32(len(oldCommittee)+len(newCommittee)) { - assert.Equal(t, len(oldCommittee), endedOldCommittee) - t.Logf("Resharing done. Reshared %d participants", reSharingEnded) - - // xj tests: BigXj == xj*G - for j, key := range newKeys { - // xj test: BigXj == xj*G - xj := key.Xi - gXj := crypto.ScalarBaseMult(tss.Edwards(), xj) - BigXj := key.BigXj[j] - assert.True(t, BigXj.Equals(gXj), "ensure BigX_j == g^x_j") - } - - // more verification of signing is implemented within local_party_test.go of keygen package - goto signing - } - } - } - -signing: - // PHASE: signing - signKeys, signPIDs := newKeys, newPIDs - signP2pCtx := tss.NewPeerContext(signPIDs) - signParties := make([]*signing.LocalParty, 0, len(signPIDs)) - - signErrCh := make(chan *tss.Error, len(signPIDs)) - signOutCh := make(chan tss.Message, len(signPIDs)) - signEndCh := make(chan *common.SignatureData, len(signPIDs)) - - for j, signPID := range signPIDs { - params := tss.NewParameters(tss.Edwards(), signP2pCtx, signPID, len(signPIDs), newThreshold) - P := signing.NewLocalParty(big.NewInt(42), params, signKeys[j], signOutCh, signEndCh).(*signing.LocalParty) - signParties = append(signParties, P) - go func(P *signing.LocalParty) { - if err := P.Start(); err != nil { - signErrCh <- err - } - }(P) - } - - var signEnded int32 - for { - select { - case err := <-signErrCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - return - - case msg := <-signOutCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range signParties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, signErrCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(signParties[dest[0].Index], msg, signErrCh) - } - - case signData := <-signEndCh: - atomic.AddInt32(&signEnded, 1) - if atomic.LoadInt32(&signEnded) == int32(len(signPIDs)) { - t.Logf("Signing done. Received sign data from %d participants", signEnded) - - // BEGIN EDDSA verify - pkX, pkY := signKeys[0].EDDSAPub.X(), signKeys[0].EDDSAPub.Y() - pk := edwards.PublicKey{ - Curve: tss.Edwards(), - X: pkX, - Y: pkY, - } - - newSig, err := edwards.ParseSignature(signData.Signature) - if err != nil { - println("new sig error, ", err.Error()) - } - - ok := edwards.Verify(&pk, big.NewInt(42).Bytes(), - newSig.R, newSig.S) - - assert.True(t, ok, "eddsa verify must pass") - t.Log("EDDSA signing test done.") - // END EDDSA verify - - return - } - } - } -} diff --git a/tss-lib/eddsa/resharing/messages.go b/tss-lib/eddsa/resharing/messages.go index d51a7ce..1076edf 100644 --- a/tss-lib/eddsa/resharing/messages.go +++ b/tss-lib/eddsa/resharing/messages.go @@ -1,170 +1,120 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package resharing import ( - "crypto/elliptic" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -// These messages were generated from Protocol Buffers definitions into eddsa-resharing.pb.go - -var ( - // Ensure that signing messages implement ValidateBasic - _ = []tss.MessageContent{ - (*DGRound1Message)(nil), - (*DGRound2Message)(nil), - (*DGRound3Message1)(nil), - (*DGRound3Message2)(nil), - (*DGRound4Message)(nil), - } -) - -// ----- // - -func NewDGRound1Message( - to []*tss.PartyID, - from *tss.PartyID, - eddsaPub *crypto.ECPoint, - vct cmt.HashCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: to, - IsBroadcast: true, - IsToOldCommittee: false, - } - content := &DGRound1Message{ - EddsaPubX: eddsaPub.X().Bytes(), - EddsaPubY: eddsaPub.Y().Bytes(), - VCommitment: vct.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// DGRound1Message is broadcast by old committee: EdDSA pub + VSS commitment. +type DGRound1Message struct { + EDDSAPub *crypto.ECPoint + VCommitment *big.Int } +// ValidateBasic checks that required fields of DGRound1Message are non-nil. func (m *DGRound1Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.EddsaPubX) && - common.NonEmptyBytes(m.EddsaPubY) && - common.NonEmptyBytes(m.VCommitment) + return m != nil && m.EDDSAPub != nil && + m.VCommitment != nil && m.VCommitment.Sign() > 0 } -func (m *DGRound1Message) UnmarshalEDDSAPub(ec elliptic.Curve) (*crypto.ECPoint, error) { - return crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.EddsaPubX), - new(big.Int).SetBytes(m.EddsaPubY)) +// NewDGRound1Message constructs a *tss.Message with the given content. +func NewDGRound1Message(to []*tss.PartyID, from *tss.PartyID, eddsaPub *crypto.ECPoint, vct cmt.HashCommitment) *tss.Message { + return &tss.Message{ + From: from, + To: to, + IsBroadcast: true, + Content: &DGRound1Message{ + EDDSAPub: eddsaPub, + VCommitment: vct, + }, + } } -func (m *DGRound1Message) UnmarshalVCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetVCommitment()) -} +// DGRound2Message is an ACK broadcast from new to old committee. +type DGRound2Message struct{} -// ----- // +// ValidateBasic checks that the receiver is non-nil. +func (m *DGRound2Message) ValidateBasic() bool { return m != nil } -func NewDGRound2Message( - to []*tss.PartyID, - from *tss.PartyID, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewDGRound2Message constructs a *tss.Message with the given content. +func NewDGRound2Message(to []*tss.PartyID, from *tss.PartyID) *tss.Message { + return &tss.Message{ From: from, To: to, IsBroadcast: true, IsToOldCommittee: true, + Content: &DGRound2Message{}, } - content := &DGRound2Message{} - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *DGRound2Message) ValidateBasic() bool { - return true -} - -// ----- // - -func NewDGRound3Message1( - to *tss.PartyID, - from *tss.PartyID, - share *vss.Share, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: []*tss.PartyID{to}, - IsBroadcast: false, - IsToOldCommittee: false, - } - content := &DGRound3Message1{ - Share: share.Share.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) +// DGRound3Message1 is P2P from old to new: VSS share. +type DGRound3Message1 struct { + Share *big.Int + ReceiverID []byte } +// ValidateBasic checks that required fields of DGRound3Message1 are non-nil. func (m *DGRound3Message1) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.Share) + return m != nil && m.Share != nil && m.Share.Sign() > 0 && + len(m.ReceiverID) > 0 } -// ----- // - -func NewDGRound3Message2( - to []*tss.PartyID, - from *tss.PartyID, - vdct cmt.HashDeCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ - From: from, - To: to, - IsBroadcast: true, - IsToOldCommittee: false, +// NewDGRound3Message1 constructs a *tss.Message with the given content. +func NewDGRound3Message1(to *tss.PartyID, from *tss.PartyID, share *vss.Share) *tss.Message { + return &tss.Message{ + From: from, + To: []*tss.PartyID{to}, + Content: &DGRound3Message1{ + Share: share.Share, + ReceiverID: to.Key, + }, } - vDctBzs := common.BigIntsToBytes(vdct) - content := &DGRound3Message2{ - VDecommitment: vDctBzs, - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } +// DGRound3Message2 is broadcast by old committee: VSS decommitment. +type DGRound3Message2 struct { + VDeCommitment cmt.HashDeCommitment +} + +// ValidateBasic checks that the decommitment has enough elements. func (m *DGRound3Message2) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.VDecommitment) + return m != nil && len(m.VDeCommitment) >= 2 } -func (m *DGRound3Message2) UnmarshalVDeCommitment() cmt.HashDeCommitment { - deComBzs := m.GetVDecommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) +// NewDGRound3Message2 constructs a *tss.Message with the given content. +func NewDGRound3Message2(to []*tss.PartyID, from *tss.PartyID, vdct cmt.HashDeCommitment) *tss.Message { + return &tss.Message{ + From: from, + To: to, + IsBroadcast: true, + Content: &DGRound3Message2{ + VDeCommitment: vdct, + }, + } } -// ----- // +// DGRound4Message is an ACK broadcast to both committees. +type DGRound4Message struct{} -func NewDGRound4Message( - to []*tss.PartyID, - from *tss.PartyID, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// ValidateBasic checks that the receiver is non-nil. +func (m *DGRound4Message) ValidateBasic() bool { return m != nil } + +// NewDGRound4Message constructs a *tss.Message with the given content. +func NewDGRound4Message(to []*tss.PartyID, from *tss.PartyID) *tss.Message { + return &tss.Message{ From: from, To: to, IsBroadcast: true, IsToOldAndNewCommittees: true, + Content: &DGRound4Message{}, } - content := &DGRound4Message{} - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *DGRound4Message) ValidateBasic() bool { - return true } diff --git a/tss-lib/eddsa/resharing/negative_test.go b/tss-lib/eddsa/resharing/negative_test.go new file mode 100644 index 0000000..2a2afcc --- /dev/null +++ b/tss-lib/eddsa/resharing/negative_test.go @@ -0,0 +1,167 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// runKeygenForReshare does a 3-party EdDSA keygen and returns saves + party IDs. +func runKeygenForReshare(t *testing.T) ([]keygen.LocalPartySaveData, tss.SortedPartyIDs) { + t.Helper() + const n = 3 + const threshold = 1 + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(params) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(states[i], r1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves, pIDs +} + +// --- ReshareRound2 error paths --- + +func TestReshareRound2InvalidR1Message(t *testing.T) { + saves, oldPIDs := runKeygenForReshare(t) + newPIDs := tss.GenerateTestPartyIDs(3) + + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + // Run Round1 for old committee + oldN := len(oldPIDs) + newN := len(newPIDs) + r1Msgs := make([]*tss.Message, oldN) + var newState *ReshareState + + for i := 0; i < oldN; i++ { + params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, oldPIDs[i], oldN, 1, newN, 1) + st, out, err := ReshareRound1(params, &saves[i]) + if err != nil { + t.Fatalf("ReshareRound1[%d]: %v", i, err) + } + if len(out.Messages) > 0 { + r1Msgs[i] = out.Messages[0] + } + _ = st + } + + // New committee party + params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, newPIDs[0], oldN, 1, newN, 1) + st, _, err := ReshareRound1(params, nil) + if err != nil { + t.Fatalf("ReshareRound1 new: %v", err) + } + newState = st + + // Corrupt r1[0]: nil EDDSAPub + badR1 := make([]*tss.Message, oldN) + copy(badR1, r1Msgs) + badR1[0] = &tss.Message{ + From: r1Msgs[0].From, + Content: &DGRound1Message{EDDSAPub: nil, VCommitment: big.NewInt(1)}, + } + + _, err = ReshareRound2(newState, badR1) + if err == nil { + t.Fatal("expected error for invalid round 1 message") + } +} + +func TestReshareRound2PubKeyMismatch(t *testing.T) { + saves, oldPIDs := runKeygenForReshare(t) + newPIDs := tss.GenerateTestPartyIDs(3) + + oldCtx := tss.NewPeerContext(oldPIDs) + newCtx := tss.NewPeerContext(newPIDs) + + oldN := len(oldPIDs) + newN := len(newPIDs) + r1Msgs := make([]*tss.Message, oldN) + + for i := 0; i < oldN; i++ { + params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, oldPIDs[i], oldN, 1, newN, 1) + _, out, err := ReshareRound1(params, &saves[i]) + if err != nil { + t.Fatalf("ReshareRound1[%d]: %v", i, err) + } + if len(out.Messages) > 0 { + r1Msgs[i] = out.Messages[0] + } + } + + // New party + params := tss.NewReSharingParameters( + tss.Edwards(), oldCtx, newCtx, newPIDs[0], oldN, 1, newN, 1) + st, _, err := ReshareRound1(params, nil) + if err != nil { + t.Fatalf("ReshareRound1 new: %v", err) + } + + // Replace r1[1]'s EDDSAPub with a different key + differentKey := crypto.ScalarBaseMult(tss.Edwards(), big.NewInt(99999)) + badR1 := make([]*tss.Message, oldN) + copy(badR1, r1Msgs) + badContent := *r1Msgs[1].Content.(*DGRound1Message) + badContent.EDDSAPub = differentKey + badR1[1] = &tss.Message{From: r1Msgs[1].From, Content: &badContent} + + _, err = ReshareRound2(st, badR1) + if err == nil { + t.Fatal("expected error for pub key mismatch") + } +} diff --git a/tss-lib/eddsa/resharing/round_1_old_step_1.go b/tss-lib/eddsa/resharing/round_1_old_step_1.go deleted file mode 100644 index c9bed9b..0000000 --- a/tss-lib/eddsa/resharing/round_1_old_step_1.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - "fmt" - - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/eddsa/signing" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// round 1 represents round 1 of the keygen part of the EDDSA TSS spec -func newRound1(params *tss.ReSharingParameters, input, save *keygen.LocalPartySaveData, temp *localTempData, out chan<- tss.Message, end chan<- *keygen.LocalPartySaveData) tss.Round { - return &round1{ - &base{params, temp, input, save, out, end, make([]bool, len(params.OldParties().IDs())), make([]bool, len(params.NewParties().IDs())), false, 1}, - } -} - -func (round *round1) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 1 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - round.allNewOK() - - if !round.ReSharingParams().IsOldCommittee() { - return nil - } - round.allOldOK() - - Pi := round.PartyID() - i := Pi.Index - - // 1. PrepareForSigning() -> w_i - xi, ks := round.input.Xi, round.input.Ks - if round.Threshold()+1 > len(ks) { - return round.WrapError(fmt.Errorf("t+1=%d is not satisfied by the key count of %d", round.Threshold()+1, len(ks)), round.PartyID()) - } - newKs := round.NewParties().IDs().Keys() - wi := signing.PrepareForSigning(round.Params().EC(), i, len(round.OldParties().IDs()), xi, ks) - - // 2. - vi, shares, err := vss.Create(round.Params().EC(), round.NewThreshold(), wi, newKs, round.Rand()) - if err != nil { - return round.WrapError(err, round.PartyID()) - } - - // 3. - flatVis, err := crypto.FlattenECPoints(vi) - if err != nil { - return round.WrapError(err, round.PartyID()) - } - vCmt := commitments.NewHashCommitment(round.Rand(), flatVis...) - - // 4. populate temp data - round.temp.VD = vCmt.D - round.temp.NewShares = shares - - // 5. "broadcast" C_i to members of the NEW committee - r1msg := NewDGRound1Message( - round.NewParties().IDs().Exclude(round.PartyID()), round.PartyID(), - round.input.EDDSAPub, vCmt.C) - round.temp.dgRound1Messages[i] = r1msg - round.out <- r1msg - - return nil -} - -func (round *round1) CanAccept(msg tss.ParsedMessage) bool { - // accept messages from old -> new committee - if _, ok := msg.Content().(*DGRound1Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round1) Update() (bool, *tss.Error) { - // only the new committee receive in this round - if !round.ReSharingParameters.IsNewCommittee() { - return true, nil - } - // accept messages from old -> new committee - ret := true - for j, msg := range round.temp.dgRound1Messages { - if round.oldOK[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.oldOK[j] = true - - if round.temp.dgRound1Messages[0] == nil { - ret = false - continue - } - // save the eddsa pub received from the old committee - r1msg := round.temp.dgRound1Messages[0].Content().(*DGRound1Message) - candidate, err := r1msg.UnmarshalEDDSAPub(round.Params().EC()) - if err != nil { - return false, round.WrapError(errors.New("unable to unmarshal the eddsa pub key"), msg.GetFrom()) - } - if round.save.EDDSAPub != nil && - !candidate.Equals(round.save.EDDSAPub) { - // uh oh - anomaly! - return false, round.WrapError(errors.New("eddsa pub key did not match what we received previously"), msg.GetFrom()) - } - round.save.EDDSAPub = candidate - } - return ret, nil -} - -func (round *round1) NextRound() tss.Round { - round.started = false - return &round2{round} -} diff --git a/tss-lib/eddsa/resharing/round_2_new_step_1.go b/tss-lib/eddsa/resharing/round_2_new_step_1.go deleted file mode 100644 index 734ae7b..0000000 --- a/tss-lib/eddsa/resharing/round_2_new_step_1.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round2) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 2 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - round.allOldOK() - - if !round.ReSharingParams().IsNewCommittee() { - return nil - } - round.allNewOK() - - Pi := round.PartyID() - i := Pi.Index - - // 1. "broadcast" "ACK" members of the OLD committee - r2msg := NewDGRound2Message(round.OldParties().IDs(), Pi) - round.temp.dgRound2Messages[i] = r2msg - round.out <- r2msg - - return nil -} - -func (round *round2) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*DGRound2Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round2) Update() (bool, *tss.Error) { - // only the old committee receive in this round - if !round.ReSharingParams().IsOldCommittee() { - return true, nil - } - - ret := true - // accept messages from new -> old committee - for j, msg := range round.temp.dgRound2Messages { - if round.newOK[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.newOK[j] = true - } - - return ret, nil -} - -func (round *round2) NextRound() tss.Round { - round.started = false - return &round3{round} -} diff --git a/tss-lib/eddsa/resharing/round_3_old_step_2.go b/tss-lib/eddsa/resharing/round_3_old_step_2.go deleted file mode 100644 index bb991cc..0000000 --- a/tss-lib/eddsa/resharing/round_3_old_step_2.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round3) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 3 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - round.allNewOK() - - if !round.ReSharingParams().IsOldCommittee() { - return nil - } - round.allOldOK() - - Pi := round.PartyID() - i := Pi.Index - - // 1-2. send share to Pj from the new committee - for j, Pj := range round.NewParties().IDs() { - share := round.temp.NewShares[j] - r3msg1 := NewDGRound3Message1(Pj, round.PartyID(), share) - round.temp.dgRound3Message1s[i] = r3msg1 - round.out <- r3msg1 - } - - // 3. broadcast de-commitment to new committees - vDeCmt := round.temp.VD - r3msg2 := NewDGRound3Message2( - round.NewParties().IDs().Exclude(round.PartyID()), round.PartyID(), - vDeCmt) - round.temp.dgRound3Message2s[i] = r3msg2 - round.out <- r3msg2 - - return nil -} - -func (round *round3) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*DGRound3Message1); ok { - return !msg.IsBroadcast() - } - if _, ok := msg.Content().(*DGRound3Message2); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round3) Update() (bool, *tss.Error) { - // only the new committee receive in this round - if !round.ReSharingParams().IsNewCommittee() { - return true, nil - } - - // accept messages from old -> new committee - for j, msg1 := range round.temp.dgRound3Message1s { - if round.oldOK[j] { - continue - } - if msg1 == nil || !round.CanAccept(msg1) { - return false, nil - } - msg2 := round.temp.dgRound3Message2s[j] - if msg2 == nil || !round.CanAccept(msg2) { - return false, nil - } - round.oldOK[j] = true - } - return true, nil -} - -func (round *round3) NextRound() tss.Round { - round.started = false - return &round4{round} -} diff --git a/tss-lib/eddsa/resharing/round_4_new_step_2.go b/tss-lib/eddsa/resharing/round_4_new_step_2.go deleted file mode 100644 index a40537c..0000000 --- a/tss-lib/eddsa/resharing/round_4_new_step_2.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "math/big" - - "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/vss" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round4) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 4 - round.started = true - round.resetOK() // resets both round.oldOK and round.newOK - - round.allOldOK() - - if !round.ReSharingParams().IsNewCommittee() { - // both committees proceed to round 5 after receiving "ACK" messages from the new committee - return nil - } - - Pi := round.PartyID() - i := Pi.Index - - // 1. - newXi := big.NewInt(0) - - // 2-8. - modQ := common.ModInt(round.Params().EC().Params().N) - vjc := make([][]*crypto.ECPoint, len(round.OldParties().IDs())) - for j := 0; j <= len(vjc)-1; j++ { // P1..P_t+1. Ps are indexed from 0 here - r1msg := round.temp.dgRound1Messages[j].Content().(*DGRound1Message) - r3msg2 := round.temp.dgRound3Message2s[j].Content().(*DGRound3Message2) - - vCj, vDj := r1msg.UnmarshalVCommitment(), r3msg2.UnmarshalVDeCommitment() - - // 3. unpack flat "v" commitment content - vCmtDeCmt := commitments.HashCommitDecommit{C: vCj, D: vDj} - ok, flatVs := vCmtDeCmt.DeCommit() - if !ok || len(flatVs) != (round.NewThreshold()+1)*2 { // they're points so * 2 - // TODO collect culprits and return a list of them as per convention - return round.WrapError(errors.New("de-commitment of v_j0..v_jt failed"), round.Parties().IDs()[j]) - } - vj, err := crypto.UnFlattenECPoints(round.Params().EC(), flatVs) - if err != nil { - return round.WrapError(err, round.Parties().IDs()[j]) - } - - for i, v := range vj { - vj[i] = v.EightInvEight() - } - - vjc[j] = vj - - r3msg1 := round.temp.dgRound3Message1s[j].Content().(*DGRound3Message1) - sharej := &vss.Share{ - Threshold: round.NewThreshold(), - ID: round.PartyID().KeyInt(), - Share: new(big.Int).SetBytes(r3msg1.Share), - } - if ok := sharej.Verify(round.Params().EC(), round.NewThreshold(), vj); !ok { - return round.WrapError(errors.New("share from old committee did not pass Verify()"), round.Parties().IDs()[j]) - } - - newXi = new(big.Int).Add(newXi, sharej.Share) - } - - // 9-12. - var err error - Vc := make([]*crypto.ECPoint, round.NewThreshold()+1) - for c := 0; c <= round.NewThreshold(); c++ { - Vc[c] = vjc[0][c] - for j := 1; j <= len(vjc)-1; j++ { - Vc[c], err = Vc[c].Add(vjc[j][c]) - if err != nil { - return round.WrapError(errors.Wrapf(err, "Vc[c].Add(vjc[j][c])")) - } - } - } - - // 13-15. - if !Vc[0].Equals(round.save.EDDSAPub) { - return round.WrapError(errors.New("assertion failed: V_0 != y"), round.PartyID()) - } - - // 16-20. - newKs := make([]*big.Int, 0, round.NewPartyCount()) - newBigXjs := make([]*crypto.ECPoint, round.NewPartyCount()) - culprits := make([]*tss.PartyID, 0, round.NewPartyCount()) // who caused the error(s) - for j := 0; j < round.NewPartyCount(); j++ { - Pj := round.NewParties().IDs()[j] - kj := Pj.KeyInt() - newBigXj := Vc[0] - newKs = append(newKs, kj) - z := new(big.Int).SetInt64(int64(1)) - for c := 1; c <= round.NewThreshold(); c++ { - z = modQ.Mul(z, kj) - newBigXj, err = newBigXj.Add(Vc[c].ScalarMult(z)) - if err != nil { - culprits = append(culprits, Pj) - } - } - newBigXjs[j] = newBigXj - } - if len(culprits) > 0 { - return round.WrapError(errors.Wrapf(err, "newBigXj.Add(Vc[c].ScalarMult(z))"), culprits...) - } - - round.temp.newXi = newXi - round.temp.newKs = newKs - round.temp.newBigXjs = newBigXjs - - // 21. Send an "ACK" message to both committees to signal that we're ready to save our data - r4msg := NewDGRound4Message(round.OldAndNewParties(), Pi) - round.temp.dgRound4Messages[i] = r4msg - round.out <- r4msg - - return nil -} - -func (round *round4) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*DGRound4Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round4) Update() (bool, *tss.Error) { - // accept messages from new -> old&new committees - ret := true - for j, msg := range round.temp.dgRound4Messages { - if round.newOK[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.newOK[j] = true - } - return ret, nil -} - -func (round *round4) NextRound() tss.Round { - round.started = false - return &round5{round} -} diff --git a/tss-lib/eddsa/resharing/round_5_new_step_3.go b/tss-lib/eddsa/resharing/round_5_new_step_3.go deleted file mode 100644 index 953ec71..0000000 --- a/tss-lib/eddsa/resharing/round_5_new_step_3.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "errors" - - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round5) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 5 - round.started = true - - round.allOldOK() - round.allNewOK() - - if round.IsNewCommittee() { - // for this P: SAVE data - round.save.BigXj = round.temp.newBigXjs - round.save.ShareID = round.PartyID().KeyInt() - round.save.Xi = round.temp.newXi - round.save.Ks = round.temp.newKs - - } else if round.IsOldCommittee() { - round.input.Xi.SetInt64(0) - } - - round.end <- round.save - return nil -} - -func (round *round5) CanAccept(msg tss.ParsedMessage) bool { - return false -} - -func (round *round5) Update() (bool, *tss.Error) { - return false, nil -} - -func (round *round5) NextRound() tss.Round { - return nil // both committees are finished! -} diff --git a/tss-lib/eddsa/resharing/round_fn.go b/tss-lib/eddsa/resharing/round_fn.go new file mode 100644 index 0000000..fd9e5d9 --- /dev/null +++ b/tss-lib/eddsa/resharing/round_fn.go @@ -0,0 +1,338 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "bytes" + "errors" + "fmt" + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/eddsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// oldIndex returns this party's index in the old committee, or -1. +func oldIndex(params *tss.ReSharingParameters) int { + key := params.PartyID().KeyInt() + for i, pid := range params.OldParties().IDs() { + if pid.KeyInt().Cmp(key) == 0 { + return i + } + } + return -1 +} + +// newIndex returns this party's index in the new committee, or -1. +func newIndex(params *tss.ReSharingParameters) int { + key := params.PartyID().KeyInt() + for i, pid := range params.NewParties().IDs() { + if pid.KeyInt().Cmp(key) == 0 { + return i + } + } + return -1 +} + +// getReshareSSID computes the session ID for domain separation. +func getReshareSSID(params *tss.ReSharingParameters, temp *localTempData) ([]byte, error) { + ssidList := []*big.Int{ + new(big.Int).SetBytes([]byte("eddsa-resharing")), + params.EC().Params().P, params.EC().Params().N, + params.EC().Params().B, + params.EC().Params().Gx, params.EC().Params().Gy, + } + ssidList = append(ssidList, params.OldParties().IDs().Keys()...) + ssidList = append(ssidList, params.NewParties().IDs().Keys()...) + ssidList = append(ssidList, big.NewInt(int64(params.PartyCount()))) + ssidList = append(ssidList, big.NewInt(int64(params.Threshold()))) + ssidList = append(ssidList, big.NewInt(int64(params.NewThreshold()))) + ssidList = append(ssidList, temp.ssidNonce) + if cid := params.CeremonyID(); len(cid) > 0 { + ssidList = append(ssidList, new(big.Int).SetBytes(cid)) + } + return common.SHA512_256i(ssidList...).Bytes(), nil +} + +// ReshareRound1 is executed by the OLD committee. It computes +// Lagrange-interpolated wi, creates VSS shares for the new committee, +// and broadcasts a commitment. +// +// New committee parties call this too but get a no-op (nil messages). +func ReshareRound1(params *tss.ReSharingParameters, input *keygen.LocalPartySaveData) (*ReshareState, *ReshareRoundOutput, error) { + oldPC := params.OldPartyCount() + newPC := params.NewPartyCount() + + temp := &localTempData{ + localMessageStore: localMessageStore{ + dgRound1Messages: make([]*tss.Message, oldPC), + dgRound2Messages: make([]*tss.Message, newPC), + dgRound3Message1s: make([]*tss.Message, oldPC), + dgRound3Message2s: make([]*tss.Message, oldPC), + dgRound4Messages: make([]*tss.Message, newPC), + }, + } + save := keygen.NewLocalPartySaveData(newPC) + + temp.ssidNonce = new(big.Int).SetUint64(uint64(params.SSIDNonce())) + + state := &ReshareState{params: params, input: input, save: &save, temp: *temp} + + if !params.IsOldCommittee() { + return state, &ReshareRoundOutput{}, nil + } + + ssid, err := getReshareSSID(params, &state.temp) + if err != nil { + return nil, nil, fmt.Errorf("round 1 SSID: %w", err) + } + state.temp.ssid = ssid + + Pi := params.PartyID() + i := oldIndex(params) + + // Lagrange interpolation. + xi, ks := input.Xi, input.Ks + if params.Threshold()+1 > len(ks) { + return nil, nil, fmt.Errorf("t+1=%d not satisfied by key count %d", params.Threshold()+1, len(ks)) + } + wi := signing.PrepareForSigning(params.EC(), i, len(params.OldParties().IDs()), xi, ks) + + // VSS create for new committee. + newKs := params.NewParties().IDs().Keys() + vi, shares, _, err := vss.Create(params.EC(), params.NewThreshold(), wi, newKs, params.Rand()) + if err != nil { + return nil, nil, fmt.Errorf("round 1 vss create: %w", err) + } + + // Commitment. + flatVis, err := crypto.FlattenECPoints(vi) + if err != nil { + return nil, nil, fmt.Errorf("round 1 flatten: %w", err) + } + vCmt := commitments.NewHashCommitment(params.Rand(), flatVis...) + + state.temp.VD = vCmt.D + state.temp.NewShares = shares + + r1msg := NewDGRound1Message( + params.NewParties().IDs().Exclude(Pi), Pi, + input.EDDSAPub, vCmt.C) + state.temp.dgRound1Messages[i] = r1msg + + return state, &ReshareRoundOutput{Messages: []*tss.Message{r1msg}}, nil +} + +// ReshareRound2 is executed by the NEW committee. It validates that +// all old parties agree on the EdDSA public key, then sends an ACK +// to the old committee. +// +// Old committee parties call this too but get a no-op. +func ReshareRound2(state *ReshareState, r1Msgs []*tss.Message) (*ReshareRoundOutput, error) { + params := state.params + + if !params.IsNewCommittee() { + return &ReshareRoundOutput{}, nil + } + + // Validate all old parties agree on the same EdDSA pub key. + for j, msg := range r1Msgs { + r1msg := msg.Content.(*DGRound1Message) + if !r1msg.ValidateBasic() { + return nil, tss.NewError(errors.New("invalid round 1 message"), TaskName, 2, + params.PartyID(), msg.From) + } + candidate := r1msg.EDDSAPub + if state.save.EDDSAPub != nil && !candidate.Equals(state.save.EDDSAPub) { + return nil, tss.NewError(errors.New("eddsa pub key mismatch"), TaskName, 2, + params.PartyID(), msg.From) + } + state.save.EDDSAPub = candidate + state.temp.dgRound1Messages[j] = msg + } + + Pi := params.PartyID() + i := newIndex(params) + + r2msg := NewDGRound2Message(params.OldParties().IDs(), Pi) + state.temp.dgRound2Messages[i] = r2msg + + return &ReshareRoundOutput{Messages: []*tss.Message{r2msg}}, nil +} + +// ReshareRound3 is executed by the OLD committee. It sends P2P +// VSS shares and broadcasts the decommitment to the new committee. +// +// New committee parties call this too but get a no-op. +func ReshareRound3(state *ReshareState, r2AckMsgs []*tss.Message) (*ReshareRoundOutput, error) { + params := state.params + + if !params.IsOldCommittee() { + return &ReshareRoundOutput{}, nil + } + + Pi := params.PartyID() + i := oldIndex(params) + + // P2P shares to new committee. + msgs := make([]*tss.Message, 0, params.NewPartyCount()+1) + for j, Pj := range params.NewParties().IDs() { + share := state.temp.NewShares[j] + r3msg1 := NewDGRound3Message1(Pj, Pi, share) + state.temp.dgRound3Message1s[i] = r3msg1 + msgs = append(msgs, r3msg1) + } + + // Broadcast decommitment. + r3msg2 := NewDGRound3Message2( + params.NewParties().IDs().Exclude(Pi), Pi, + state.temp.VD) + state.temp.dgRound3Message2s[i] = r3msg2 + msgs = append(msgs, r3msg2) + + return &ReshareRoundOutput{Messages: msgs}, nil +} + +// ReshareRound4 is executed by the NEW committee. It verifies all +// decommitments and VSS shares, computes the new key share and +// BigXj, and sends an ACK to both committees. +// +// Old committee parties call this too but get a no-op. +func ReshareRound4(state *ReshareState, r1Msgs []*tss.Message, r3p2p []*tss.Message, r3bcast []*tss.Message) (*ReshareRoundOutput, error) { + params := state.params + + if !params.IsNewCommittee() { + return &ReshareRoundOutput{}, nil + } + + Pi := params.PartyID() + i := newIndex(params) + oldPC := params.OldPartyCount() + modQ := common.ModInt(params.EC().Params().N) + + // Verify decommitments, shares, accumulate newXi. + newXi := big.NewInt(0) + vjc := make([][]*crypto.ECPoint, oldPC) + + for j := 0; j < oldPC; j++ { + r1msg := r1Msgs[j].Content.(*DGRound1Message) + r3msg2 := r3bcast[j].Content.(*DGRound3Message2) + + vCmtDeCmt := commitments.HashCommitDecommit{C: r1msg.VCommitment, D: r3msg2.VDeCommitment} + ok, flatVs := vCmtDeCmt.DeCommit() + if !ok || len(flatVs) != (params.NewThreshold()+1)*2 { + return nil, tss.NewError(errors.New("de-commitment of v_j0..v_jt failed"), + TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + vj, err := crypto.UnFlattenECPoints(params.EC(), flatVs) + if err != nil { + return nil, tss.NewError(fmt.Errorf("unflatten: %w", err), + TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + // Cofactor clearing for Edwards curve. + for k := range vj { + vj[k] = vj[k].EightInvEight() + } + vjc[j] = vj + + // Verify receiver binding + share. + r3msg1 := r3p2p[j].Content.(*DGRound3Message1) + if !bytes.Equal(r3msg1.ReceiverID, Pi.Key) { + return nil, tss.NewError(errors.New("receiverId mismatch"), + TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + sharej := &vss.Share{ + Threshold: params.NewThreshold(), + ID: Pi.KeyInt(), + Share: r3msg1.Share, + } + if !sharej.Verify(params.EC(), params.NewThreshold(), vj) { + return nil, tss.NewError(errors.New("share verify failed"), + TaskName, 4, Pi, params.OldParties().IDs()[j]) + } + newXi = new(big.Int).Add(newXi, sharej.Share) + } + + newXi = new(big.Int).Mod(newXi, params.EC().Params().N) + if newXi.Sign() == 0 { + return nil, tss.NewError(errors.New("newXi is zero"), TaskName, 4, Pi) + } + + // Compute Vc = sum of vjc columns. + Vc := make([]*crypto.ECPoint, params.NewThreshold()+1) + for c := 0; c <= params.NewThreshold(); c++ { + Vc[c] = vjc[0][c] + for j := 1; j < oldPC; j++ { + var err error + Vc[c], err = Vc[c].Add(vjc[j][c]) + if err != nil { + return nil, tss.NewError(fmt.Errorf("Vc[c].Add: %w", err), TaskName, 4, Pi) + } + } + } + + // Verify V_0 == EdDSA pub key. + if !Vc[0].Equals(state.save.EDDSAPub) { + return nil, tss.NewError(errors.New("V_0 != EdDSA pub key"), TaskName, 4, Pi) + } + + // Compute new BigXj for each new party. + newKs := make([]*big.Int, 0, params.NewPartyCount()) + newBigXjs := make([]*crypto.ECPoint, params.NewPartyCount()) + for j := 0; j < params.NewPartyCount(); j++ { + Pj := params.NewParties().IDs()[j] + kj := Pj.KeyInt() + newKs = append(newKs, kj) + BigXj := Vc[0] + z := new(big.Int).SetInt64(1) + for c := 1; c <= params.NewThreshold(); c++ { + z = modQ.Mul(z, kj) + var err error + BigXj, err = BigXj.Add(Vc[c].ScalarMult(z)) + if err != nil { + return nil, tss.NewError(fmt.Errorf("BigXj computation failed: %w", err), + TaskName, 4, Pi, Pj) + } + } + if BigXj.IsIdentity() { + return nil, tss.NewError(errors.New("BigXj is the identity point"), + TaskName, 4, Pi, Pj) + } + newBigXjs[j] = BigXj + } + + state.temp.newXi = newXi + state.temp.newKs = newKs + state.temp.newBigXjs = newBigXjs + + // ACK to both committees. + r4msg := NewDGRound4Message(params.OldAndNewParties(), Pi) + state.temp.dgRound4Messages[i] = r4msg + + return &ReshareRoundOutput{Messages: []*tss.Message{r4msg}}, nil +} + +// ReshareRound5 finalizes the resharing. New committee parties save +// their new key material. Old committee parties zero their old Xi. +func ReshareRound5(state *ReshareState, r4AckMsgs []*tss.Message) (*ReshareRoundOutput, error) { + if state.params.IsNewCommittee() { + state.save.BigXj = state.temp.newBigXjs + state.save.ShareID = state.params.PartyID().KeyInt() + state.save.Xi = state.temp.newXi + state.save.Ks = state.temp.newKs + } + // Zero old Xi — including dual-committee parties. + if state.params.IsOldCommittee() { + state.input.Xi.SetInt64(0) + } + + return &ReshareRoundOutput{Save: state.save}, nil +} diff --git a/tss-lib/eddsa/resharing/round_fn_test.go b/tss-lib/eddsa/resharing/round_fn_test.go new file mode 100644 index 0000000..c2bc685 --- /dev/null +++ b/tss-lib/eddsa/resharing/round_fn_test.go @@ -0,0 +1,269 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "crypto/sha256" + "math/big" + "testing" + + "github.com/decred/dcrd/dcrec/edwards/v2" + + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/eddsa/signing" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TestRoundFnEdDSAReshareAndSign runs a full reshare from a 3-party +// old committee (t=1) to a 3-party new committee (t=1), then signs +// with the new committee and verifies the signature. +func TestRoundFnEdDSAReshareAndSign(t *testing.T) { + const oldN = 3 + const oldT = 1 + const newN = 3 + const newT = 1 + + // --- Keygen with old committee --- + oldPIDs := tss.GenerateTestPartyIDs(oldN) + oldPeerCtx := tss.NewPeerContext(oldPIDs) + oldSaves := doKeygen(t, oldN, oldT, oldPIDs, oldPeerCtx) + + oldPubKey := oldSaves[0].EDDSAPub + t.Logf("old pub key: (%x, %x)", oldPubKey.X(), oldPubKey.Y()) + + // --- Create new party IDs (different from old) --- + newPIDs := tss.GenerateTestPartyIDs(newN) + newPeerCtx := tss.NewPeerContext(newPIDs) + + // --- Reshare Round 1 (old committee) --- + oldStates := make([]*ReshareState, oldN) + r1Msgs := make([]*tss.Message, oldN) + for i := 0; i < oldN; i++ { + params := tss.NewReSharingParameters( + tss.Edwards(), oldPeerCtx, newPeerCtx, + oldPIDs[i], oldN, oldT, newN, newT) + st, out, err := ReshareRound1(params, &oldSaves[i]) + if err != nil { + t.Fatalf("ReshareRound1[old %d]: %v", i, err) + } + oldStates[i] = st + if len(out.Messages) > 0 { + r1Msgs[i] = out.Messages[0] + } + } + + // New committee also calls Round1 (no-op for them) + newStates := make([]*ReshareState, newN) + for i := 0; i < newN; i++ { + params := tss.NewReSharingParameters( + tss.Edwards(), oldPeerCtx, newPeerCtx, + newPIDs[i], oldN, oldT, newN, newT) + st, _, err := ReshareRound1(params, nil) + if err != nil { + t.Fatalf("ReshareRound1[new %d]: %v", i, err) + } + newStates[i] = st + } + + // --- Reshare Round 2 (new committee sends ACK) --- + r2Msgs := make([]*tss.Message, newN) + for i := 0; i < newN; i++ { + out, err := ReshareRound2(newStates[i], r1Msgs) + if err != nil { + t.Fatalf("ReshareRound2[new %d]: %v", i, err) + } + if len(out.Messages) > 0 { + r2Msgs[i] = out.Messages[0] + } + } + // Old committee also calls Round2 (no-op) + for i := 0; i < oldN; i++ { + if _, err := ReshareRound2(oldStates[i], nil); err != nil { + t.Fatalf("ReshareRound2[old %d]: %v", i, err) + } + } + + // --- Reshare Round 3 (old committee sends shares + decommitment) --- + r3p2p := make([][]*tss.Message, newN) // [new_receiver][old_sender] + r3bcast := make([]*tss.Message, oldN) // [old_sender] + for i := range r3p2p { + r3p2p[i] = make([]*tss.Message, oldN) + } + for i := 0; i < oldN; i++ { + out, err := ReshareRound3(oldStates[i], r2Msgs) + if err != nil { + t.Fatalf("ReshareRound3[old %d]: %v", i, err) + } + for _, msg := range out.Messages { + switch msg.Content.(type) { + case *DGRound3Message2: + // Broadcast decommitment. + r3bcast[i] = msg + case *DGRound3Message1: + // P2P share to specific new party. + for _, to := range msg.To { + r3p2p[to.Index][i] = msg + } + } + } + } + // New committee also calls Round3 (no-op) + for i := 0; i < newN; i++ { + if _, err := ReshareRound3(newStates[i], nil); err != nil { + t.Fatalf("ReshareRound3[new %d]: %v", i, err) + } + } + + // --- Reshare Round 4 (new committee verifies + ACK) --- + r4Msgs := make([]*tss.Message, newN) + for i := 0; i < newN; i++ { + out, err := ReshareRound4(newStates[i], r1Msgs, r3p2p[i], r3bcast) + if err != nil { + t.Fatalf("ReshareRound4[new %d]: %v", i, err) + } + if len(out.Messages) > 0 { + r4Msgs[i] = out.Messages[0] + } + } + // Old committee also calls Round4 (no-op) + for i := 0; i < oldN; i++ { + if _, err := ReshareRound4(oldStates[i], nil, nil, nil); err != nil { + t.Fatalf("ReshareRound4[old %d]: %v", i, err) + } + } + + // --- Reshare Round 5 (save) --- + newSaves := make([]keygen.LocalPartySaveData, newN) + for i := 0; i < newN; i++ { + out, err := ReshareRound5(newStates[i], r4Msgs) + if err != nil { + t.Fatalf("ReshareRound5[new %d]: %v", i, err) + } + newSaves[i] = *out.Save + } + for i := 0; i < oldN; i++ { + out, err := ReshareRound5(oldStates[i], nil) + if err != nil { + t.Fatalf("ReshareRound5[old %d]: %v", i, err) + } + // Old Xi should be zeroed. + if oldSaves[i].Xi.Sign() != 0 { + t.Fatalf("old party %d Xi not zeroed", i) + } + _ = out + } + + // Verify new saves: same pub key, valid data. + for i := 0; i < newN; i++ { + if !newSaves[i].EDDSAPub.Equals(oldPubKey) { + t.Fatalf("new party %d: EDDSAPub changed after reshare", i) + } + if err := newSaves[i].ValidateSaveData(); err != nil { + t.Fatalf("new party %d ValidateSaveData: %v", i, err) + } + t.Logf("new party %d: EDDSAPub = (%x, %x)", i, + newSaves[i].EDDSAPub.X(), newSaves[i].EDDSAPub.Y()) + } + + // --- Sign with new committee --- + msgHash := sha256.Sum256([]byte("hello reshared eddsa")) + m := new(big.Int).SetBytes(msgHash[:]) + + sigStates := make([]*signing.SigningState, newN) + sr1 := make([]*tss.Message, newN) + for i := 0; i < newN; i++ { + params := tss.NewParameters(tss.Edwards(), newPeerCtx, newPIDs[i], newN, newT) + st, out, err := signing.SignRound1(params, newSaves[i], m, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + sigStates[i] = st + sr1[i] = out.Messages[0] + } + + sr2 := make([]*tss.Message, newN) + for i := 0; i < newN; i++ { + out, err := signing.SignRound2(sigStates[i], sr1) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + sr2[i] = out.Messages[0] + } + + sr3 := make([]*tss.Message, newN) + for i := 0; i < newN; i++ { + out, err := signing.SignRound3(sigStates[i], sr2) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + sr3[i] = out.Messages[0] + } + + out, err := signing.SignFinalize(sigStates[0], sr3) + if err != nil { + t.Fatalf("SignFinalize: %v", err) + } + + pk := edwards.PublicKey{ + Curve: tss.Edwards(), + X: newSaves[0].EDDSAPub.X(), + Y: newSaves[0].EDDSAPub.Y(), + } + r := new(big.Int).SetBytes(out.Signature.R) + s := new(big.Int).SetBytes(out.Signature.S) + if !edwards.Verify(&pk, msgHash[:], r, s) { + t.Fatal("EdDSA signature verification failed after reshare") + } + t.Logf("post-reshare signature verified: r=%x s=%x", out.Signature.R[:8], out.Signature.S[:8]) +} + +// doKeygen runs EdDSA keygen for the test. +func doKeygen(t *testing.T, n, threshold int, pIDs tss.SortedPartyIDs, peerCtx *tss.PeerContext) []keygen.LocalPartySaveData { + t.Helper() + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(params) + if err != nil { + t.Fatalf("keygen.Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(states[i], r1) + if err != nil { + t.Fatalf("keygen.Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("keygen.Round3[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves +} diff --git a/tss-lib/eddsa/resharing/rounds.go b/tss-lib/eddsa/resharing/rounds.go deleted file mode 100644 index 3487849..0000000 --- a/tss-lib/eddsa/resharing/rounds.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package resharing - -import ( - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - TaskName = "eddsa-resharing" -) - -type ( - base struct { - *tss.ReSharingParameters - temp *localTempData - input, save *keygen.LocalPartySaveData - out chan<- tss.Message - end chan<- *keygen.LocalPartySaveData - oldOK, // old committee "ok" tracker - newOK []bool // `ok` tracks parties which have been verified by Update(); this one is for the new committee - started bool - number int - } - round1 struct { - *base - } - round2 struct { - *round1 - } - round3 struct { - *round2 - } - round4 struct { - *round3 - } - round5 struct { - *round4 - } -) - -var ( - _ tss.Round = (*round1)(nil) - _ tss.Round = (*round2)(nil) - _ tss.Round = (*round3)(nil) - _ tss.Round = (*round4)(nil) - _ tss.Round = (*round5)(nil) -) - -// ----- // - -func (round *base) Params() *tss.Parameters { - return round.ReSharingParameters.Parameters -} - -func (round *base) ReSharingParams() *tss.ReSharingParameters { - return round.ReSharingParameters -} - -func (round *base) RoundNumber() int { - return round.number -} - -// CanProceed is inherited by other rounds -func (round *base) CanProceed() bool { - if !round.started { - return false - } - for _, ok := range append(round.oldOK, round.newOK...) { - if !ok { - return false - } - } - return true -} - -// WaitingFor is called by a Party for reporting back to the caller -func (round *base) WaitingFor() []*tss.PartyID { - oldPs := round.OldParties().IDs() - newPs := round.NewParties().IDs() - idsMap := make(map[*tss.PartyID]bool) - ids := make([]*tss.PartyID, 0, len(round.oldOK)) - for j, ok := range round.oldOK { - if ok { - continue - } - idsMap[oldPs[j]] = true - } - for j, ok := range round.newOK { - if ok { - continue - } - idsMap[newPs[j]] = true - } - // consolidate into the list - for id := range idsMap { - ids = append(ids, id) - } - return ids -} - -func (round *base) WrapError(err error, culprits ...*tss.PartyID) *tss.Error { - return tss.NewError(err, TaskName, round.number, round.PartyID(), culprits...) -} - -// ----- // - -// `oldOK` tracks parties which have been verified by Update() -func (round *base) resetOK() { - for j := range round.oldOK { - round.oldOK[j] = false - } - for j := range round.newOK { - round.newOK[j] = false - } -} - -// sets all pairings in `oldOK` to true -func (round *base) allOldOK() { - for j := range round.oldOK { - round.oldOK[j] = true - } -} - -// sets all pairings in `newOK` to true -func (round *base) allNewOK() { - for j := range round.newOK { - round.newOK[j] = true - } -} diff --git a/tss-lib/eddsa/resharing/types.go b/tss-lib/eddsa/resharing/types.go new file mode 100644 index 0000000..636dab8 --- /dev/null +++ b/tss-lib/eddsa/resharing/types.go @@ -0,0 +1,58 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/vss" + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TaskName identifies the EdDSA resharing protocol in error messages. +const TaskName = "eddsa-resharing" + +type localTempData struct { + localMessageStore + + ssidNonce *big.Int + ssid []byte + + // Round 1 (old committee) + VD []*big.Int // decommitment + NewShares vss.Shares // shares for new committee + + // Round 4 (new committee) + newXi *big.Int + newKs []*big.Int + newBigXjs []*crypto.ECPoint +} + +type localMessageStore struct { + dgRound1Messages []*tss.Message + dgRound2Messages []*tss.Message + dgRound3Message1s []*tss.Message + dgRound3Message2s []*tss.Message + dgRound4Messages []*tss.Message +} + +// ReshareState holds mutable state across all resharing rounds. +type ReshareState struct { + params *tss.ReSharingParameters + input *keygen.LocalPartySaveData + save *keygen.LocalPartySaveData + temp localTempData +} + +// ReshareRoundOutput is returned by each round function. +type ReshareRoundOutput struct { + // Messages to send to other parties. + Messages []*tss.Message + // Save is non-nil only after the final round (new committee only). + Save *keygen.LocalPartySaveData +} diff --git a/tss-lib/eddsa/resharing/validate_test.go b/tss-lib/eddsa/resharing/validate_test.go new file mode 100644 index 0000000..a8ceee2 --- /dev/null +++ b/tss-lib/eddsa/resharing/validate_test.go @@ -0,0 +1,73 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package resharing + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestDGRound1MessageValidateBasic(t *testing.T) { + if (*DGRound1Message)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&DGRound1Message{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + ec := tss.Edwards() + pt := crypto.ScalarBaseMult(ec, big.NewInt(42)) + if !(&DGRound1Message{EDDSAPub: pt, VCommitment: big.NewInt(1)}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestDGRound2MessageValidateBasic(t *testing.T) { + if (*DGRound2Message)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if !(&DGRound2Message{}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestDGRound3Message1ValidateBasic(t *testing.T) { + if (*DGRound3Message1)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&DGRound3Message1{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + if (&DGRound3Message1{Share: big.NewInt(1)}).ValidateBasic() { + t.Fatal("missing ReceiverID should fail") + } + if !(&DGRound3Message1{Share: big.NewInt(1), ReceiverID: []byte("x")}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestDGRound3Message2ValidateBasic(t *testing.T) { + if (*DGRound3Message2)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&DGRound3Message2{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + if !(&DGRound3Message2{VDeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestDGRound4MessageValidateBasic(t *testing.T) { + if (*DGRound4Message)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if !(&DGRound4Message{}).ValidateBasic() { + t.Fatal("valid should pass") + } +} diff --git a/tss-lib/eddsa/signing/eddsa-signing.pb.go b/tss-lib/eddsa/signing/eddsa-signing.pb.go deleted file mode 100644 index 1f130e0..0000000 --- a/tss-lib/eddsa/signing/eddsa-signing.pb.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.14.0 -// source: protob/eddsa-signing.proto - -package signing - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// -// Represents a BROADCAST message sent to all parties during Round 1 of the EDDSA TSS signing protocol. -type SignRound1Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` -} - -func (x *SignRound1Message) Reset() { - *x = SignRound1Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_signing_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound1Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound1Message) ProtoMessage() {} - -func (x *SignRound1Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_signing_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound1Message.ProtoReflect.Descriptor instead. -func (*SignRound1Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_signing_proto_rawDescGZIP(), []int{0} -} - -func (x *SignRound1Message) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 2 of the EDDSA TSS signing protocol. -type SignRound2Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeCommitment [][]byte `protobuf:"bytes,1,rep,name=de_commitment,json=deCommitment,proto3" json:"de_commitment,omitempty"` - ProofAlphaX []byte `protobuf:"bytes,2,opt,name=proof_alpha_x,json=proofAlphaX,proto3" json:"proof_alpha_x,omitempty"` - ProofAlphaY []byte `protobuf:"bytes,3,opt,name=proof_alpha_y,json=proofAlphaY,proto3" json:"proof_alpha_y,omitempty"` - ProofT []byte `protobuf:"bytes,4,opt,name=proof_t,json=proofT,proto3" json:"proof_t,omitempty"` -} - -func (x *SignRound2Message) Reset() { - *x = SignRound2Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_signing_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound2Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound2Message) ProtoMessage() {} - -func (x *SignRound2Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_signing_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound2Message.ProtoReflect.Descriptor instead. -func (*SignRound2Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_signing_proto_rawDescGZIP(), []int{1} -} - -func (x *SignRound2Message) GetDeCommitment() [][]byte { - if x != nil { - return x.DeCommitment - } - return nil -} - -func (x *SignRound2Message) GetProofAlphaX() []byte { - if x != nil { - return x.ProofAlphaX - } - return nil -} - -func (x *SignRound2Message) GetProofAlphaY() []byte { - if x != nil { - return x.ProofAlphaY - } - return nil -} - -func (x *SignRound2Message) GetProofT() []byte { - if x != nil { - return x.ProofT - } - return nil -} - -// -// Represents a BROADCAST message sent to all parties during Round 3 of the EDDSA TSS signing protocol. -type SignRound3Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - S []byte `protobuf:"bytes,1,opt,name=s,proto3" json:"s,omitempty"` -} - -func (x *SignRound3Message) Reset() { - *x = SignRound3Message{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_eddsa_signing_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignRound3Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignRound3Message) ProtoMessage() {} - -func (x *SignRound3Message) ProtoReflect() protoreflect.Message { - mi := &file_protob_eddsa_signing_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignRound3Message.ProtoReflect.Descriptor instead. -func (*SignRound3Message) Descriptor() ([]byte, []int) { - return file_protob_eddsa_signing_proto_rawDescGZIP(), []int{2} -} - -func (x *SignRound3Message) GetS() []byte { - if x != nil { - return x.S - } - return nil -} - -var File_protob_eddsa_signing_proto protoreflect.FileDescriptor - -var file_protob_eddsa_signing_proto_rawDesc = []byte{ - 0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x65, 0x64, 0x64, 0x73, 0x61, 0x2d, 0x73, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x62, 0x69, - 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x64, 0x64, - 0x73, 0x61, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x33, 0x0a, 0x11, 0x53, 0x69, - 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0x99, 0x01, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x58, 0x12, 0x22, - 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5f, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x6c, 0x70, 0x68, - 0x61, 0x59, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x22, 0x21, 0x0a, 0x11, 0x53, - 0x69, 0x67, 0x6e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x0c, 0x0a, 0x01, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x01, 0x73, 0x42, 0x0f, - 0x5a, 0x0d, 0x65, 0x64, 0x64, 0x73, 0x61, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_protob_eddsa_signing_proto_rawDescOnce sync.Once - file_protob_eddsa_signing_proto_rawDescData = file_protob_eddsa_signing_proto_rawDesc -) - -func file_protob_eddsa_signing_proto_rawDescGZIP() []byte { - file_protob_eddsa_signing_proto_rawDescOnce.Do(func() { - file_protob_eddsa_signing_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_eddsa_signing_proto_rawDescData) - }) - return file_protob_eddsa_signing_proto_rawDescData -} - -var file_protob_eddsa_signing_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_protob_eddsa_signing_proto_goTypes = []interface{}{ - (*SignRound1Message)(nil), // 0: binance.tsslib.eddsa.signing.SignRound1Message - (*SignRound2Message)(nil), // 1: binance.tsslib.eddsa.signing.SignRound2Message - (*SignRound3Message)(nil), // 2: binance.tsslib.eddsa.signing.SignRound3Message -} -var file_protob_eddsa_signing_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_protob_eddsa_signing_proto_init() } -func file_protob_eddsa_signing_proto_init() { - if File_protob_eddsa_signing_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_eddsa_signing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound1Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_signing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound2Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_eddsa_signing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignRound3Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_eddsa_signing_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_eddsa_signing_proto_goTypes, - DependencyIndexes: file_protob_eddsa_signing_proto_depIdxs, - MessageInfos: file_protob_eddsa_signing_proto_msgTypes, - }.Build() - File_protob_eddsa_signing_proto = out.File - file_protob_eddsa_signing_proto_rawDesc = nil - file_protob_eddsa_signing_proto_goTypes = nil - file_protob_eddsa_signing_proto_depIdxs = nil -} diff --git a/tss-lib/eddsa/signing/finalize.go b/tss-lib/eddsa/signing/finalize.go deleted file mode 100644 index 21f8d4e..0000000 --- a/tss-lib/eddsa/signing/finalize.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "fmt" - "math/big" - - "github.com/binance-chain/edwards25519" - "github.com/decred/dcrd/dcrec/edwards/v2" - - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *finalization) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 4 - round.started = true - round.resetOK() - - sumS := round.temp.si - for j := range round.Parties().IDs() { - round.ok[j] = true - if j == round.PartyID().Index { - continue - } - r3msg := round.temp.signRound3Messages[j].Content().(*SignRound3Message) - sjBytes := bigIntToEncodedBytes(r3msg.UnmarshalS()) - var tmpSumS [32]byte - edwards25519.ScMulAdd(&tmpSumS, sumS, bigIntToEncodedBytes(big.NewInt(1)), sjBytes) - sumS = &tmpSumS - } - s := encodedBytesToBigInt(sumS) - - // save the signature for final output - round.data.Signature = append(bigIntToEncodedBytes(round.temp.r)[:], sumS[:]...) - round.data.R = round.temp.r.Bytes() - round.data.S = s.Bytes() - if round.temp.fullBytesLen == 0 { - round.data.M = round.temp.m.Bytes() - } else { - mBytes := make([]byte, round.temp.fullBytesLen) - round.temp.m.FillBytes(mBytes) - round.data.M = mBytes - } - - pk := edwards.PublicKey{ - Curve: round.Params().EC(), - X: round.key.EDDSAPub.X(), - Y: round.key.EDDSAPub.Y(), - } - - ok := edwards.Verify(&pk, round.data.M, round.temp.r, s) - if !ok { - return round.WrapError(fmt.Errorf("signature verification failed")) - } - round.end <- round.data - - return nil -} - -func (round *finalization) CanAccept(msg tss.ParsedMessage) bool { - // not expecting any incoming messages in this round - return false -} - -func (round *finalization) Update() (bool, *tss.Error) { - // not expecting any incoming messages in this round - return false, nil -} - -func (round *finalization) NextRound() tss.Round { - return nil // finished! -} diff --git a/tss-lib/eddsa/signing/local_party.go b/tss-lib/eddsa/signing/local_party.go deleted file mode 100644 index 950a272..0000000 --- a/tss-lib/eddsa/signing/local_party.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// Implements Party -// Implements Stringer -var _ tss.Party = (*LocalParty)(nil) -var _ fmt.Stringer = (*LocalParty)(nil) - -type ( - LocalParty struct { - *tss.BaseParty - params *tss.Parameters - - keys keygen.LocalPartySaveData - temp localTempData - data *common.SignatureData - - // outbound messaging - out chan<- tss.Message - end chan<- *common.SignatureData - } - - localMessageStore struct { - signRound1Messages, - signRound2Messages, - signRound3Messages []tss.ParsedMessage - } - - localTempData struct { - localMessageStore - - // temp data (thrown away after sign) / round 1 - wi, - m, - ri *big.Int - fullBytesLen int - pointRi *crypto.ECPoint - deCommit cmt.HashDeCommitment - - // round 2 - cjs []*big.Int - si *[32]byte - - // round 3 - r *big.Int - - ssid []byte - ssidNonce *big.Int - } -) - -func NewLocalParty( - msg *big.Int, - params *tss.Parameters, - key keygen.LocalPartySaveData, - out chan<- tss.Message, - end chan<- *common.SignatureData, - fullBytesLen ...int, -) tss.Party { - partyCount := len(params.Parties().IDs()) - p := &LocalParty{ - BaseParty: new(tss.BaseParty), - params: params, - keys: keygen.BuildLocalSaveDataSubset(key, params.Parties().IDs()), - temp: localTempData{}, - data: &common.SignatureData{}, - out: out, - end: end, - } - // msgs init - p.temp.signRound1Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound2Messages = make([]tss.ParsedMessage, partyCount) - p.temp.signRound3Messages = make([]tss.ParsedMessage, partyCount) - - // temp data init - p.temp.m = msg - if len(fullBytesLen) > 0 { - p.temp.fullBytesLen = fullBytesLen[0] - } else { - p.temp.fullBytesLen = 0 - } - p.temp.cjs = make([]*big.Int, partyCount) - return p -} - -func (p *LocalParty) FirstRound() tss.Round { - return newRound1(p.params, &p.keys, p.data, &p.temp, p.out, p.end) -} - -func (p *LocalParty) Start() *tss.Error { - return tss.BaseStart(p, TaskName, func(round tss.Round) *tss.Error { - round1, ok := round.(*round1) - if !ok { - return round.WrapError(errors.New("unable to Start(). party is in an unexpected round")) - } - if err := round1.prepare(); err != nil { - return round.WrapError(err) - } - return nil - }) -} - -func (p *LocalParty) Update(msg tss.ParsedMessage) (ok bool, err *tss.Error) { - return tss.BaseUpdate(p, msg, TaskName) -} - -func (p *LocalParty) UpdateFromBytes(wireBytes []byte, from *tss.PartyID, isBroadcast bool) (bool, *tss.Error) { - msg, err := tss.ParseWireMessage(wireBytes, from, isBroadcast) - if err != nil { - return false, p.WrapError(err) - } - return p.Update(msg) -} - -func (p *LocalParty) ValidateMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - if msg.GetFrom() == nil || !msg.GetFrom().ValidateBasic() { - return false, p.WrapError(fmt.Errorf("received msg with an invalid sender: %s", msg)) - } - // check that the message's "from index" will fit into the array - if maxFromIdx := len(p.params.Parties().IDs()) - 1; maxFromIdx < msg.GetFrom().Index { - return false, p.WrapError(fmt.Errorf("received msg with a sender index too great (%d <= %d)", - maxFromIdx, msg.GetFrom().Index), msg.GetFrom()) - } - return p.BaseParty.ValidateMessage(msg) -} - -func (p *LocalParty) StoreMessage(msg tss.ParsedMessage) (bool, *tss.Error) { - // ValidateBasic is cheap; double-check the message here in case the public StoreMessage was called externally - if ok, err := p.ValidateMessage(msg); !ok || err != nil { - return ok, err - } - fromPIdx := msg.GetFrom().Index - - // switch/case is necessary to store any messages beyond current round - // this does not handle message replays. we expect the caller to apply replay and spoofing protection. - switch msg.Content().(type) { - case *SignRound1Message: - p.temp.signRound1Messages[fromPIdx] = msg - - case *SignRound2Message: - p.temp.signRound2Messages[fromPIdx] = msg - - case *SignRound3Message: - p.temp.signRound3Messages[fromPIdx] = msg - - default: // unrecognised message, just ignore! - common.Logger.Warningf("unrecognised message ignored: %v", msg) - return false, nil - } - return true, nil -} - -func (p *LocalParty) PartyID() *tss.PartyID { - return p.params.PartyID() -} - -func (p *LocalParty) String() string { - return fmt.Sprintf("id: %s, %s", p.PartyID(), p.BaseParty.String()) -} diff --git a/tss-lib/eddsa/signing/local_party_test.go b/tss-lib/eddsa/signing/local_party_test.go deleted file mode 100644 index 3ea5866..0000000 --- a/tss-lib/eddsa/signing/local_party_test.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "encoding/hex" - "fmt" - "math/big" - "sync/atomic" - "testing" - - "github.com/binance-chain/edwards25519" - "github.com/decred/dcrd/dcrec/edwards/v2" - "github.com/ipfs/go-log" - "github.com/stretchr/testify/assert" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/test" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - testParticipants = test.TestParticipants - testThreshold = test.TestThreshold -) - -func setUp(level string) { - if err := log.SetLogLevel("tss-lib", level); err != nil { - panic(err) - } - - // only for test - tss.SetCurve(tss.Edwards()) -} - -func TestE2EConcurrent(t *testing.T) { - setUp("info") - - threshold := testThreshold - - // PHASE: load keygen fixtures - keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) - assert.NoError(t, err, "should load keygen fixtures") - assert.Equal(t, testThreshold+1, len(keys)) - assert.Equal(t, testThreshold+1, len(signPIDs)) - - // PHASE: signing - - p2pCtx := tss.NewPeerContext(signPIDs) - parties := make([]*LocalParty, 0, len(signPIDs)) - - errCh := make(chan *tss.Error, len(signPIDs)) - outCh := make(chan tss.Message, len(signPIDs)) - endCh := make(chan *common.SignatureData, len(signPIDs)) - - updater := test.SharedPartyUpdater - - msg := big.NewInt(200) - // init the parties - for i := 0; i < len(signPIDs); i++ { - params := tss.NewParameters(tss.Edwards(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - - P := NewLocalParty(msg, params, keys[i], outCh, endCh).(*LocalParty) - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - var ended int32 -signing: - for { - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break signing - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case <-endCh: - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { - t.Logf("Done. Received signature data from %d participants", ended) - R := parties[0].temp.r - - // BEGIN check s correctness - sumS := parties[0].temp.si - for i, p := range parties { - if i == 0 { - continue - } - - var tmpSumS [32]byte - edwards25519.ScMulAdd(&tmpSumS, sumS, bigIntToEncodedBytes(big.NewInt(1)), p.temp.si) - sumS = &tmpSumS - } - fmt.Printf("S: %s\n", encodedBytesToBigInt(sumS).String()) - fmt.Printf("R: %s\n", R.String()) - // END check s correctness - - // BEGIN EDDSA verify - pkX, pkY := keys[0].EDDSAPub.X(), keys[0].EDDSAPub.Y() - pk := edwards.PublicKey{ - Curve: tss.Edwards(), - X: pkX, - Y: pkY, - } - - newSig, err := edwards.ParseSignature(parties[0].data.Signature) - if err != nil { - println("new sig error, ", err.Error()) - } - - ok := edwards.Verify(&pk, msg.Bytes(), newSig.R, newSig.S) - assert.True(t, ok, "eddsa verify must pass") - t.Log("EDDSA signing test done.") - // END EDDSA verify - - break signing - } - } - } -} - -func TestE2EConcurrentWithLeadingZeroInMSG(t *testing.T) { - setUp("info") - - threshold := testThreshold - - // PHASE: load keygen fixtures - keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) - assert.NoError(t, err, "should load keygen fixtures") - assert.Equal(t, testThreshold+1, len(keys)) - assert.Equal(t, testThreshold+1, len(signPIDs)) - - // PHASE: signing - - p2pCtx := tss.NewPeerContext(signPIDs) - parties := make([]*LocalParty, 0, len(signPIDs)) - - errCh := make(chan *tss.Error, len(signPIDs)) - outCh := make(chan tss.Message, len(signPIDs)) - endCh := make(chan *common.SignatureData, len(signPIDs)) - - updater := test.SharedPartyUpdater - - msg, _ := hex.DecodeString("00f163ee51bcaeff9cdff5e0e3c1a646abd19885fffbab0b3b4236e0cf95c9f5") - // init the parties - for i := 0; i < len(signPIDs); i++ { - params := tss.NewParameters(tss.Edwards(), p2pCtx, signPIDs[i], len(signPIDs), threshold) - P := NewLocalParty(new(big.Int).SetBytes(msg), params, keys[i], outCh, endCh, len(msg)).(*LocalParty) - parties = append(parties, P) - go func(P *LocalParty) { - if err := P.Start(); err != nil { - errCh <- err - } - }(P) - } - - var ended int32 -signing: - for { - select { - case err := <-errCh: - common.Logger.Errorf("Error: %s", err) - assert.FailNow(t, err.Error()) - break signing - - case msg := <-outCh: - dest := msg.GetTo() - if dest == nil { - for _, P := range parties { - if P.PartyID().Index == msg.GetFrom().Index { - continue - } - go updater(P, msg, errCh) - } - } else { - if dest[0].Index == msg.GetFrom().Index { - t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) - } - go updater(parties[dest[0].Index], msg, errCh) - } - - case <-endCh: - atomic.AddInt32(&ended, 1) - if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { - t.Logf("Done. Received signature data from %d participants", ended) - R := parties[0].temp.r - - // BEGIN check s correctness - sumS := parties[0].temp.si - for i, p := range parties { - if i == 0 { - continue - } - - var tmpSumS [32]byte - edwards25519.ScMulAdd(&tmpSumS, sumS, bigIntToEncodedBytes(big.NewInt(1)), p.temp.si) - sumS = &tmpSumS - } - fmt.Printf("S: %s\n", encodedBytesToBigInt(sumS).String()) - fmt.Printf("R: %s\n", R.String()) - // END check s correctness - - // BEGIN EDDSA verify - pkX, pkY := keys[0].EDDSAPub.X(), keys[0].EDDSAPub.Y() - pk := edwards.PublicKey{ - Curve: tss.Edwards(), - X: pkX, - Y: pkY, - } - - newSig, err := edwards.ParseSignature(parties[0].data.Signature) - if err != nil { - println("new sig error, ", err.Error()) - } - - ok := edwards.Verify(&pk, msg, newSig.R, newSig.S) - assert.True(t, ok, "eddsa verify must pass") - t.Log("EDDSA signing test done.") - // END EDDSA verify - - break signing - } - } - } -} diff --git a/tss-lib/eddsa/signing/messages.go b/tss-lib/eddsa/signing/messages.go index e0eb86f..b16c5d2 100644 --- a/tss-lib/eddsa/signing/messages.go +++ b/tss-lib/eddsa/signing/messages.go @@ -1,131 +1,79 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package signing import ( - "crypto/elliptic" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - cmt "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" ) -// These messages were generated from Protocol Buffers definitions into eddsa-signing.pb.go -// The following messages are registered on the Protocol Buffers "wire" - -var ( - // Ensure that signing messages implement ValidateBasic - _ = []tss.MessageContent{ - (*SignRound1Message)(nil), - (*SignRound2Message)(nil), - (*SignRound3Message)(nil), - } -) +// SignRound1Message is broadcast: commitment to Ri. +type SignRound1Message struct { + Commitment *big.Int +} -// ----- // +// ValidateBasic checks that required fields of SignRound1Message are non-nil. +func (m *SignRound1Message) ValidateBasic() bool { + return m != nil && m.Commitment != nil && m.Commitment.Sign() > 0 +} -func NewSignRound1Message( - from *tss.PartyID, - commitment cmt.HashCommitment, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound1Message constructs a *tss.Message with the given content. +func NewSignRound1Message(from *tss.PartyID, commitment cmt.HashCommitment) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound1Message{ + Commitment: commitment, + }, } - content := &SignRound1Message{ - Commitment: commitment.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *SignRound1Message) ValidateBasic() bool { - return m.Commitment != nil && - common.NonEmptyBytes(m.GetCommitment()) +// SignRound2Message is broadcast: decommitment + Schnorr proof for ri. +type SignRound2Message struct { + DeCommitment cmt.HashDeCommitment + ZKProof *schnorr.ZKProof } -func (m *SignRound1Message) UnmarshalCommitment() *big.Int { - return new(big.Int).SetBytes(m.GetCommitment()) +// ValidateBasic checks that required fields of SignRound2Message are non-nil. +func (m *SignRound2Message) ValidateBasic() bool { + return m != nil && len(m.DeCommitment) >= 2 && m.ZKProof != nil } -// ----- // - -func NewSignRound2Message( - from *tss.PartyID, - deCommitment cmt.HashDeCommitment, - proof *schnorr.ZKProof, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound2Message constructs a *tss.Message with the given content. +func NewSignRound2Message(from *tss.PartyID, deCommitment cmt.HashDeCommitment, proof *schnorr.ZKProof) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound2Message{ + DeCommitment: deCommitment, + ZKProof: proof, + }, } - dcBzs := common.BigIntsToBytes(deCommitment) - content := &SignRound2Message{ - DeCommitment: dcBzs, - ProofAlphaX: proof.Alpha.X().Bytes(), - ProofAlphaY: proof.Alpha.Y().Bytes(), - ProofT: proof.T.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) } -func (m *SignRound2Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyMultiBytes(m.DeCommitment, 3) && - common.NonEmptyBytes(m.ProofAlphaX) && - common.NonEmptyBytes(m.ProofAlphaY) && - common.NonEmptyBytes(m.ProofT) +// SignRound3Message is broadcast: partial signature si. +type SignRound3Message struct { + S *big.Int } -func (m *SignRound2Message) UnmarshalDeCommitment() []*big.Int { - deComBzs := m.GetDeCommitment() - return cmt.NewHashDeCommitmentFromBytes(deComBzs) -} - -func (m *SignRound2Message) UnmarshalZKProof(ec elliptic.Curve) (*schnorr.ZKProof, error) { - point, err := crypto.NewECPoint( - ec, - new(big.Int).SetBytes(m.GetProofAlphaX()), - new(big.Int).SetBytes(m.GetProofAlphaY())) - if err != nil { - return nil, err - } - return &schnorr.ZKProof{ - Alpha: point, - T: new(big.Int).SetBytes(m.GetProofT()), - }, nil +// ValidateBasic checks that required fields of SignRound3Message are non-nil. +func (m *SignRound3Message) ValidateBasic() bool { + return m != nil && m.S != nil && m.S.Sign() > 0 } -// ----- // - -func NewSignRound3Message( - from *tss.PartyID, - si *big.Int, -) tss.ParsedMessage { - meta := tss.MessageRouting{ +// NewSignRound3Message constructs a *tss.Message with the given content. +func NewSignRound3Message(from *tss.PartyID, si *big.Int) *tss.Message { + return &tss.Message{ From: from, IsBroadcast: true, + Content: &SignRound3Message{ + S: si, + }, } - content := &SignRound3Message{ - S: si.Bytes(), - } - msg := tss.NewMessageWrapper(meta, content) - return tss.NewMessage(meta, content, msg) -} - -func (m *SignRound3Message) ValidateBasic() bool { - return m != nil && - common.NonEmptyBytes(m.S) -} - -func (m *SignRound3Message) UnmarshalS() *big.Int { - return new(big.Int).SetBytes(m.S) } diff --git a/tss-lib/eddsa/signing/negative_test.go b/tss-lib/eddsa/signing/negative_test.go new file mode 100644 index 0000000..eabc68d --- /dev/null +++ b/tss-lib/eddsa/signing/negative_test.go @@ -0,0 +1,253 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "crypto/sha256" + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// runEdDSAKeygen performs a 3-party keygen for signing tests. +func runEdDSAKeygen(t *testing.T) ([]keygen.LocalPartySaveData, tss.SortedPartyIDs) { + t.Helper() + const n = 3 + const threshold = 1 + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(params) + if err != nil { + t.Fatalf("keygen Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(states[i], r1) + if err != nil { + t.Fatalf("keygen Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("keygen Round3[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves, pIDs +} + +// --- SignRound1 error paths --- + +func TestSignRound1NilXi(t *testing.T) { + saves, pIDs := runEdDSAKeygen(t) + peerCtx := tss.NewPeerContext(pIDs) + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[0], 3, 1) + + bad := saves[0] + bad.Xi = nil + _, _, err := SignRound1(params, bad, big.NewInt(42), 0) + if err == nil { + t.Fatal("expected error for nil Xi") + } +} + +func TestSignRound1NilEDDSAPub(t *testing.T) { + saves, pIDs := runEdDSAKeygen(t) + peerCtx := tss.NewPeerContext(pIDs) + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[0], 3, 1) + + bad := saves[0] + bad.EDDSAPub = nil + _, _, err := SignRound1(params, bad, big.NewInt(42), 0) + if err == nil { + t.Fatal("expected error for nil EDDSAPub") + } +} + +func TestSignRound1WrongKeyCount(t *testing.T) { + saves, pIDs := runEdDSAKeygen(t) + peerCtx := tss.NewPeerContext(pIDs) + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[0], 3, 1) + + bad := saves[0] + bad.Ks = bad.Ks[:1] // wrong count + _, _, err := SignRound1(params, bad, big.NewInt(42), 0) + if err == nil { + t.Fatal("expected error for wrong key count") + } +} + +// --- SignRound2 error paths --- + +func TestSignRound2InvalidR1(t *testing.T) { + saves, pIDs := runEdDSAKeygen(t) + peerCtx := tss.NewPeerContext(pIDs) + + msg := sha256.Sum256([]byte("test")) + m := new(big.Int).SetBytes(msg[:]) + + states := make([]*SigningState, 3) + r1 := make([]*tss.Message, 3) + for i := 0; i < 3; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], 3, 1) + st, out, err := SignRound1(params, saves[i], m, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + // Corrupt r1[1] + badR1 := make([]*tss.Message, 3) + copy(badR1, r1) + badR1[1] = &tss.Message{ + From: r1[1].From, + Content: &SignRound1Message{Commitment: nil}, + } + + _, err := SignRound2(states[0], badR1) + if err == nil { + t.Fatal("expected error for invalid round 1 message") + } +} + +// --- SignRound3 error paths --- + +func runToSignRound3(t *testing.T) ([]*SigningState, []*tss.Message, tss.SortedPartyIDs) { + t.Helper() + saves, pIDs := runEdDSAKeygen(t) + peerCtx := tss.NewPeerContext(pIDs) + msg := sha256.Sum256([]byte("test")) + m := new(big.Int).SetBytes(msg[:]) + + states := make([]*SigningState, 3) + r1 := make([]*tss.Message, 3) + for i := 0; i < 3; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], 3, 1) + st, out, err := SignRound1(params, saves[i], m, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2 := make([]*tss.Message, 3) + for i := 0; i < 3; i++ { + out, err := SignRound2(states[i], r1) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + r2[i] = out.Messages[0] + } + return states, r2, pIDs +} + +func TestSignRound3BadDeCommitment(t *testing.T) { + states, r2, _ := runToSignRound3(t) + + badR2 := make([]*tss.Message, 3) + copy(badR2, r2) + badContent := *r2[1].Content.(*SignRound2Message) + badContent.DeCommitment = nil + badR2[1] = &tss.Message{From: r2[1].From, Content: &badContent} + + _, err := SignRound3(states[0], badR2) + if err == nil { + t.Fatal("expected error for bad decommitment") + } +} + +func TestSignRound3MissingProof(t *testing.T) { + states, r2, _ := runToSignRound3(t) + + badR2 := make([]*tss.Message, 3) + copy(badR2, r2) + badContent := *r2[1].Content.(*SignRound2Message) + badContent.ZKProof = nil + badR2[1] = &tss.Message{From: r2[1].From, Content: &badContent} + + _, err := SignRound3(states[0], badR2) + if err == nil { + t.Fatal("expected error for missing proof") + } +} + +func TestSignRound3WrongProof(t *testing.T) { + states, r2, _ := runToSignRound3(t) + + badR2 := make([]*tss.Message, 3) + copy(badR2, r2) + badContent := *r2[1].Content.(*SignRound2Message) + badContent.ZKProof = &schnorr.ZKProof{Alpha: nil, T: big.NewInt(99)} + badR2[1] = &tss.Message{From: r2[1].From, Content: &badContent} + + _, err := SignRound3(states[0], badR2) + if err == nil { + t.Fatal("expected error for wrong proof") + } +} + +// --- SignFinalize error paths --- + +func TestSignFinalizeOutOfRangeS(t *testing.T) { + states, r2, _ := runToSignRound3(t) + + r3 := make([]*tss.Message, 3) + for i := 0; i < 3; i++ { + out, err := SignRound3(states[i], r2) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + + // Corrupt s value: set to -1 (out of range) + badR3 := make([]*tss.Message, 3) + copy(badR3, r3) + badR3[1] = &tss.Message{ + From: r3[1].From, + Content: &SignRound3Message{S: big.NewInt(-1)}, + } + + _, err := SignFinalize(states[0], badR3) + if err == nil { + t.Fatal("expected error for out-of-range s") + } +} diff --git a/tss-lib/eddsa/signing/prepare.go b/tss-lib/eddsa/signing/prepare.go index 4e7d4c2..9745989 100644 --- a/tss-lib/eddsa/signing/prepare.go +++ b/tss-lib/eddsa/signing/prepare.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package signing @@ -11,10 +10,11 @@ import ( "fmt" "math/big" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) -// PrepareForSigning(), Fig. 7 +// PrepareForSigning computes the Lagrange interpolated secret share +// wi for party i, given the party's secret xi and all party keys ks. func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int) (wi *big.Int) { modQ := common.ModInt(ec.Params().N) if len(ks) != pax { @@ -23,9 +23,7 @@ func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int if len(ks) <= i { panic(fmt.Errorf("PrepareForSigning: len(ks) <= i (%d <= %d)", len(ks), i)) } - - // 1-4. - wi = xi + wi = new(big.Int).Set(xi) for j := 0; j < pax; j++ { if j == i { continue @@ -35,10 +33,16 @@ func PrepareForSigning(ec elliptic.Curve, i, pax int, xi *big.Int, ks []*big.Int if ksj.Cmp(ksi) == 0 { panic(fmt.Errorf("index of two parties are equal")) } - // big.Int Div is calculated as: a/b = a * modInv(b,q) - coef := modQ.Mul(ks[j], modQ.ModInverse(new(big.Int).Sub(ksj, ksi))) + diff := new(big.Int).Sub(ksj, ksi) + inv := modQ.ModInverse(diff) + if inv == nil { + panic(fmt.Errorf("PrepareForSigning: ModInverse(ks[%d]-ks[%d]) is nil; keys may collide mod q", j, i)) + } + coef := modQ.Mul(ks[j], inv) wi = modQ.Mul(wi, coef) } - + if wi.Sign() == 0 { + panic(fmt.Errorf("PrepareForSigning: wi is zero after Lagrange interpolation for party %d", i)) + } return } diff --git a/tss-lib/eddsa/signing/round_1.go b/tss-lib/eddsa/signing/round_1.go deleted file mode 100644 index 6d65aaf..0000000 --- a/tss-lib/eddsa/signing/round_1.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "fmt" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -// round 1 represents round 1 of the signing part of the EDDSA TSS spec -func newRound1(params *tss.Parameters, key *keygen.LocalPartySaveData, data *common.SignatureData, temp *localTempData, out chan<- tss.Message, end chan<- *common.SignatureData) tss.Round { - return &round1{ - &base{params, key, data, temp, out, end, make([]bool, len(params.Parties().IDs())), false, 1}, - } -} - -func (round *round1) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - - round.number = 1 - round.started = true - round.resetOK() - - round.temp.ssidNonce = new(big.Int).SetUint64(0) - var err error - round.temp.ssid, err = round.getSSID() - if err != nil { - return round.WrapError(err) - } - // 1. select ri - ri := common.GetRandomPositiveInt(round.Rand(), round.Params().EC().Params().N) - - // 2. make commitment - pointRi := crypto.ScalarBaseMult(round.Params().EC(), ri) - cmt := commitments.NewHashCommitment(round.Rand(), pointRi.X(), pointRi.Y()) - - // 3. store r1 message pieces - round.temp.ri = ri - round.temp.pointRi = pointRi - round.temp.deCommit = cmt.D - - i := round.PartyID().Index - round.ok[i] = true - - // 4. broadcast commitment - r1msg2 := NewSignRound1Message(round.PartyID(), cmt.C) - round.temp.signRound1Messages[i] = r1msg2 - round.out <- r1msg2 - - return nil -} - -func (round *round1) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound1Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round1) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound1Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round1) NextRound() tss.Round { - round.started = false - return &round2{round} -} - -// ----- // - -// helper to call into PrepareForSigning() -func (round *round1) prepare() error { - i := round.PartyID().Index - - xi := round.key.Xi - ks := round.key.Ks - - if round.Threshold()+1 > len(ks) { - return fmt.Errorf("t+1=%d is not satisfied by the key count of %d", round.Threshold()+1, len(ks)) - } - wi := PrepareForSigning(round.Params().EC(), i, len(ks), xi, ks) - - round.temp.wi = wi - return nil -} diff --git a/tss-lib/eddsa/signing/round_2.go b/tss-lib/eddsa/signing/round_2.go deleted file mode 100644 index 8268fde..0000000 --- a/tss-lib/eddsa/signing/round_2.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - errors2 "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/crypto/schnorr" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round2) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - round.number = 2 - round.started = true - round.resetOK() - - i := round.PartyID().Index - - // 1. store r1 message pieces - for j, msg := range round.temp.signRound1Messages { - r1msg := msg.Content().(*SignRound1Message) - round.temp.cjs[j] = r1msg.UnmarshalCommitment() - } - - // 2. compute Schnorr prove - ContextI := append(round.temp.ssid, new(big.Int).SetUint64(uint64(i)).Bytes()...) - pir, err := schnorr.NewZKProof(ContextI, round.temp.ri, round.temp.pointRi, round.Rand()) - if err != nil { - return round.WrapError(errors2.Wrapf(err, "NewZKProof(ri, pointRi)")) - } - - // 3. BROADCAST de-commitments of Shamir poly*G and Schnorr prove - r2msg2 := NewSignRound2Message(round.PartyID(), round.temp.deCommit, pir) - round.temp.signRound2Messages[i] = r2msg2 - round.out <- r2msg2 - - return nil -} - -func (round *round2) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound2Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round2) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound2Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round2) NextRound() tss.Round { - round.started = false - return &round3{round} -} diff --git a/tss-lib/eddsa/signing/round_3.go b/tss-lib/eddsa/signing/round_3.go deleted file mode 100644 index 4089525..0000000 --- a/tss-lib/eddsa/signing/round_3.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "crypto/sha512" - "math/big" - - "github.com/binance-chain/edwards25519" - "github.com/pkg/errors" - - "github.com/hemilabs/x/tss-lib/v2/common" - - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/crypto/commitments" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func (round *round3) Start() *tss.Error { - if round.started { - return round.WrapError(errors.New("round already started")) - } - - round.number = 3 - round.started = true - round.resetOK() - - // 1. init R - var R edwards25519.ExtendedGroupElement - riBytes := bigIntToEncodedBytes(round.temp.ri) - edwards25519.GeScalarMultBase(&R, riBytes) - - // 2-6. compute R - i := round.PartyID().Index - for j, Pj := range round.Parties().IDs() { - if j == i { - continue - } - - ContextJ := common.AppendBigIntToBytesSlice(round.temp.ssid, big.NewInt(int64(j))) - msg := round.temp.signRound2Messages[j] - r2msg := msg.Content().(*SignRound2Message) - cmtDeCmt := commitments.HashCommitDecommit{C: round.temp.cjs[j], D: r2msg.UnmarshalDeCommitment()} - ok, coordinates := cmtDeCmt.DeCommit() - if !ok { - return round.WrapError(errors.New("de-commitment verify failed")) - } - if len(coordinates) != 2 { - return round.WrapError(errors.New("length of de-commitment should be 2")) - } - - Rj, err := crypto.NewECPoint(round.Params().EC(), coordinates[0], coordinates[1]) - Rj = Rj.EightInvEight() - if err != nil { - return round.WrapError(errors.Wrapf(err, "NewECPoint(Rj)"), Pj) - } - proof, err := r2msg.UnmarshalZKProof(round.Params().EC()) - if err != nil { - return round.WrapError(errors.New("failed to unmarshal Rj proof"), Pj) - } - ok = proof.Verify(ContextJ, Rj) - if !ok { - return round.WrapError(errors.New("failed to prove Rj"), Pj) - } - - extendedRj := ecPointToExtendedElement(round.Params().EC(), Rj.X(), Rj.Y(), round.Rand()) - R = addExtendedElements(R, extendedRj) - } - - // 7. compute lambda - var encodedR [32]byte - R.ToBytes(&encodedR) - encodedPubKey := ecPointToEncodedBytes(round.key.EDDSAPub.X(), round.key.EDDSAPub.Y()) - - // h = hash512(k || A || M) - h := sha512.New() - h.Reset() - h.Write(encodedR[:]) - h.Write(encodedPubKey[:]) - if round.temp.fullBytesLen == 0 { - h.Write(round.temp.m.Bytes()) - } else { - mBytes := make([]byte, round.temp.fullBytesLen) - round.temp.m.FillBytes(mBytes) - h.Write(mBytes) - } - - var lambda [64]byte - h.Sum(lambda[:0]) - var lambdaReduced [32]byte - edwards25519.ScReduce(&lambdaReduced, &lambda) - - // 8. compute si - var localS [32]byte - edwards25519.ScMulAdd(&localS, &lambdaReduced, bigIntToEncodedBytes(round.temp.wi), riBytes) - - // 9. store r3 message pieces - round.temp.si = &localS - round.temp.r = encodedBytesToBigInt(&encodedR) - - // 10. broadcast si to other parties - r3msg := NewSignRound3Message(round.PartyID(), encodedBytesToBigInt(&localS)) - round.temp.signRound3Messages[round.PartyID().Index] = r3msg - round.out <- r3msg - - return nil -} - -func (round *round3) Update() (bool, *tss.Error) { - ret := true - for j, msg := range round.temp.signRound3Messages { - if round.ok[j] { - continue - } - if msg == nil || !round.CanAccept(msg) { - ret = false - continue - } - round.ok[j] = true - } - return ret, nil -} - -func (round *round3) CanAccept(msg tss.ParsedMessage) bool { - if _, ok := msg.Content().(*SignRound3Message); ok { - return msg.IsBroadcast() - } - return false -} - -func (round *round3) NextRound() tss.Round { - round.started = false - return &finalization{round} -} diff --git a/tss-lib/eddsa/signing/round_fn.go b/tss-lib/eddsa/signing/round_fn.go new file mode 100644 index 0000000..2972840 --- /dev/null +++ b/tss-lib/eddsa/signing/round_fn.go @@ -0,0 +1,276 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "crypto/sha512" + "errors" + "fmt" + "math/big" + + decredEdwards "github.com/decred/dcrd/dcrec/edwards/v2" + + "github.com/hemilabs/x/tss-lib/v3/common" + "github.com/hemilabs/x/tss-lib/v3/crypto" + "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// getSigningSSID computes the session ID for domain separation. +func getSigningSSID(params *tss.Parameters, key *keygen.LocalPartySaveData, temp *localTempData, roundNumber int) ([]byte, error) { + ssidList := []*big.Int{ + new(big.Int).SetBytes([]byte("eddsa-signing")), + params.EC().Params().P, params.EC().Params().N, + params.EC().Params().B, + params.EC().Params().Gx, params.EC().Params().Gy, + } + ssidList = append(ssidList, params.Parties().IDs().Keys()...) + ssidList = append(ssidList, big.NewInt(int64(params.PartyCount()))) + ssidList = append(ssidList, big.NewInt(int64(params.Threshold()))) + ssidList = append(ssidList, big.NewInt(int64(roundNumber))) + ssidList = append(ssidList, temp.ssidNonce) + if cid := params.CeremonyID(); len(cid) > 0 { + ssidList = append(ssidList, new(big.Int).SetBytes(cid)) + } + return common.SHA512_256i(ssidList...).Bytes(), nil +} + +// SignRound1 initializes signing state and broadcasts a commitment +// to the signing nonce Ri. +func SignRound1(params *tss.Parameters, key keygen.LocalPartySaveData, msg *big.Int, fullBytesLen int) (*SigningState, *SignRoundOutput, error) { + if key.Xi == nil || key.Xi.Sign() == 0 { + return nil, nil, errors.New("invalid key data: Xi is nil or zero") + } + if key.EDDSAPub == nil || !key.EDDSAPub.ValidateBasic() { + return nil, nil, errors.New("invalid key data: EDDSAPub is nil or not on curve") + } + + n := params.PartyCount() + i := params.PartyID().Index + + temp := &localTempData{ + localMessageStore: localMessageStore{ + signRound1Messages: make([]*tss.Message, n), + signRound2Messages: make([]*tss.Message, n), + signRound3Messages: make([]*tss.Message, n), + }, + cjs: make([]*big.Int, n), + m: msg, + fullBytesLen: fullBytesLen, + } + + temp.ssidNonce = new(big.Int).SetUint64(uint64(params.SSIDNonce())) + ssid, err := getSigningSSID(params, &key, temp, 1) + if err != nil { + return nil, nil, fmt.Errorf("round 1 SSID: %w", err) + } + temp.ssid = ssid + + // Compute Lagrange-interpolated secret share wi. + if len(key.Ks) != n { + return nil, nil, fmt.Errorf("key count %d does not match party count %d", len(key.Ks), n) + } + wi := PrepareForSigning(params.EC(), i, n, key.Xi, key.Ks) + temp.wi = wi + + // Select signing nonce ri. + ri := common.GetRandomPositiveInt(params.Rand(), params.EC().Params().N) + temp.ri = ri + + // Compute Ri = ri*G. + pointRi := crypto.ScalarBaseMult(params.EC(), ri) + temp.pointRi = pointRi + + // Commitment. + cmt := commitments.NewHashCommitment(params.Rand(), pointRi.X(), pointRi.Y()) + temp.deCommit = cmt.D + + r1msg := NewSignRound1Message(params.PartyID(), cmt.C) + temp.signRound1Messages[i] = r1msg + + state := &SigningState{ + params: params, + key: &key, + data: &SignatureData{}, + temp: *temp, + } + return state, &SignRoundOutput{Messages: []*tss.Message{r1msg}}, nil +} + +// SignRound2 stores round 1 commitments and broadcasts the +// decommitment + Schnorr proof. +func SignRound2(state *SigningState, r1Msgs []*tss.Message) (*SignRoundOutput, error) { + params := state.params + temp := &state.temp + i := params.PartyID().Index + + // Store commitments. + for j, msg := range r1Msgs { + r1msg := msg.Content.(*SignRound1Message) + if !r1msg.ValidateBasic() { + return nil, tss.NewError(errors.New("invalid round 1 message"), TaskName, 2, params.PartyID(), msg.From) + } + temp.cjs[j] = r1msg.Commitment + } + + // Schnorr proof for ri. + ContextI := common.AppendBigIntToBytesSlice(temp.ssid, new(big.Int).SetInt64(int64(i))) + pointRi := temp.pointRi.(*crypto.ECPoint) + pir, err := schnorr.NewZKProof(ContextI, temp.ri, pointRi, params.Rand()) + if err != nil { + return nil, fmt.Errorf("round 2 schnorr proof: %w", err) + } + + r2msg := NewSignRound2Message(params.PartyID(), temp.deCommit, pir) + temp.signRound2Messages[i] = r2msg + + return &SignRoundOutput{Messages: []*tss.Message{r2msg}}, nil +} + +// SignRound3 verifies all decommitments and Schnorr proofs, +// computes the aggregate nonce R, and produces the partial +// signature si. +func SignRound3(state *SigningState, r2Msgs []*tss.Message) (*SignRoundOutput, error) { + params := state.params + temp := &state.temp + i := params.PartyID().Index + ec := params.EC() + N := ec.Params().N + + // Init R with own Ri = ri·G. + Rx, Ry := ec.ScalarBaseMult(temp.ri.Bytes()) + + // Verify each party's decommitment + proof, accumulate R. + for j, Pj := range params.Parties().IDs() { + if j == i { + continue + } + ContextJ := common.AppendBigIntToBytesSlice(temp.ssid, big.NewInt(int64(j))) + r2msg := r2Msgs[j].Content.(*SignRound2Message) + + cmtDeCmt := commitments.HashCommitDecommit{C: temp.cjs[j], D: r2msg.DeCommitment} + ok, coordinates := cmtDeCmt.DeCommit() + if !ok || len(coordinates) != 2 { + return nil, tss.NewError(errors.New("de-commitment verify failed"), TaskName, 3, params.PartyID(), Pj) + } + + Rj, err := crypto.NewECPoint(ec, coordinates[0], coordinates[1]) + if err != nil { + return nil, tss.NewError(fmt.Errorf("NewECPoint(Rj): %w", err), TaskName, 3, params.PartyID(), Pj) + } + Rj = Rj.EightInvEight() + + if r2msg.ZKProof == nil { + return nil, tss.NewError(errors.New("missing schnorr proof"), TaskName, 3, params.PartyID(), Pj) + } + if !r2msg.ZKProof.Verify(ContextJ, Rj) { + return nil, tss.NewError(errors.New("schnorr proof verify failed"), TaskName, 3, params.PartyID(), Pj) + } + + Rx, Ry = ec.Add(Rx, Ry, Rj.X(), Rj.Y()) + } + + // Encode R in Ed25519 compressed form. + encodedR := ecPointToEncodedBytes(Rx, Ry) + + // R identity check: the identity encodes as (0, 1) → LE bytes + // [0x01, 0x00, ...]. + Rpoint, err := crypto.NewECPoint(ec, Rx, Ry) + if err != nil || Rpoint.IsIdentity() { + return nil, tss.NewError(errors.New("r is the identity point"), TaskName, 3, params.PartyID()) + } + + encodedPubKey := ecPointToEncodedBytes(state.key.EDDSAPub.X(), state.key.EDDSAPub.Y()) + + h := sha512.New() + h.Write(encodedR[:]) + h.Write(encodedPubKey[:]) + if temp.fullBytesLen == 0 { + h.Write(temp.m.Bytes()) + } else { + mBytes := make([]byte, temp.fullBytesLen) + temp.m.FillBytes(mBytes) + h.Write(mBytes) + } + + var lambda [64]byte + h.Sum(lambda[:0]) + lambdaReduced := scReduce(&lambda, N) + + // Compute si = lambda*wi + ri mod N. + localS := scMulAdd(lambdaReduced, temp.wi, temp.ri, N) + + // Clear signing nonces. + temp.ri = new(big.Int) + temp.wi = new(big.Int) + + temp.si = localS + temp.r = encodedBytesToBigInt(encodedR) + + r3msg := NewSignRound3Message(params.PartyID(), localS) + temp.signRound3Messages[i] = r3msg + + return &SignRoundOutput{Messages: []*tss.Message{r3msg}}, nil +} + +// SignFinalize sums partial signatures and verifies the EdDSA signature. +func SignFinalize(state *SigningState, r3Msgs []*tss.Message) (*SignRoundOutput, error) { + params := state.params + temp := &state.temp + i := params.PartyID().Index + + if temp.si == nil { + return nil, fmt.Errorf("si is nil: round 3 did not complete") + } + sumS := temp.si + N := params.EC().Params().N + + for j := range params.Parties().IDs() { + if j == i { + continue + } + r3msg := r3Msgs[j].Content.(*SignRound3Message) + sj := r3msg.S + if sj.Sign() < 0 || sj.Cmp(N) >= 0 { + return nil, tss.NewError( + fmt.Errorf("party %d sent s_i outside [0, N)", j), + TaskName, 4, params.PartyID(), params.Parties().IDs()[j]) + } + sumS = new(big.Int).Mod(new(big.Int).Add(sumS, sj), N) + } + + if sumS.Sign() == 0 { + return nil, fmt.Errorf("accumulated S is zero: malicious share detected") + } + + // Build signature data. + data := state.data + encodedSumS := bigIntToEncodedBytes(sumS) + data.Signature = append(bigIntToEncodedBytes(temp.r)[:], encodedSumS[:]...) + data.R = temp.r.Bytes() + data.S = sumS.Bytes() + if temp.fullBytesLen == 0 { + data.M = temp.m.Bytes() + } else { + mBytes := make([]byte, temp.fullBytesLen) + temp.m.FillBytes(mBytes) + data.M = mBytes + } + + // Verify. + pk := decredEdwards.PublicKey{ + Curve: params.EC(), + X: state.key.EDDSAPub.X(), + Y: state.key.EDDSAPub.Y(), + } + if !decredEdwards.Verify(&pk, data.M, temp.r, sumS) { + return nil, fmt.Errorf("signature verification failed") + } + + return &SignRoundOutput{Signature: data}, nil +} diff --git a/tss-lib/eddsa/signing/round_fn_test.go b/tss-lib/eddsa/signing/round_fn_test.go new file mode 100644 index 0000000..5fc8a8b --- /dev/null +++ b/tss-lib/eddsa/signing/round_fn_test.go @@ -0,0 +1,137 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "crypto/sha256" + "math/big" + "testing" + + "github.com/decred/dcrd/dcrec/edwards/v2" + + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestRoundFnEdDSASignThreeParties(t *testing.T) { + const n = 3 + const threshold = 1 + + pIDs := tss.GenerateTestPartyIDs(n) + peerCtx := tss.NewPeerContext(pIDs) + + // --- Keygen --- + saves := doKeygen(t, n, threshold, pIDs, peerCtx) + + // --- Sign --- + msgHash := sha256.Sum256([]byte("hello eddsa v3")) + m := new(big.Int).SetBytes(msgHash[:]) + + // -- SignRound1 -- + sigStates := make([]*SigningState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := SignRound1(params, saves[i], m, 0) + if err != nil { + t.Fatalf("SignRound1[%d]: %v", i, err) + } + sigStates[i] = st + r1[i] = out.Messages[0] + } + + // -- SignRound2 -- + r2 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound2(sigStates[i], r1) + if err != nil { + t.Fatalf("SignRound2[%d]: %v", i, err) + } + r2[i] = out.Messages[0] + } + + // -- SignRound3 -- + r3 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + out, err := SignRound3(sigStates[i], r2) + if err != nil { + t.Fatalf("SignRound3[%d]: %v", i, err) + } + r3[i] = out.Messages[0] + } + + // -- Finalize -- + for i := 0; i < n; i++ { + out, err := SignFinalize(sigStates[i], r3) + if err != nil { + t.Fatalf("SignFinalize[%d]: %v", i, err) + } + + pk := edwards.PublicKey{ + Curve: tss.Edwards(), + X: saves[0].EDDSAPub.X(), + Y: saves[0].EDDSAPub.Y(), + } + r := new(big.Int).SetBytes(out.Signature.R) + s := new(big.Int).SetBytes(out.Signature.S) + if !edwards.Verify(&pk, msgHash[:], r, s) { + t.Fatalf("party %d: EdDSA signature verification failed", i) + } + t.Logf("party %d: sig verified (r=%x, s=%x)", i, + out.Signature.R[:8], out.Signature.S[:8]) + } +} + +// doKeygen runs EdDSA keygen for the test. +func doKeygen(t *testing.T, n, threshold int, pIDs tss.SortedPartyIDs, peerCtx *tss.PeerContext) []keygen.LocalPartySaveData { + t.Helper() + + states := make([]*keygen.KeygenState, n) + r1 := make([]*tss.Message, n) + for i := 0; i < n; i++ { + params := tss.NewParameters(tss.Edwards(), peerCtx, pIDs[i], n, threshold) + st, out, err := keygen.Round1(params) + if err != nil { + t.Fatalf("keygen.Round1[%d]: %v", i, err) + } + states[i] = st + r1[i] = out.Messages[0] + } + + r2p2p := make([][]*tss.Message, n) + r2bcast := make([]*tss.Message, n) + for i := range r2p2p { + r2p2p[i] = make([]*tss.Message, n) + } + for i := 0; i < n; i++ { + out, err := keygen.Round2(states[i], r1) + if err != nil { + t.Fatalf("keygen.Round2[%d]: %v", i, err) + } + for _, msg := range out.Messages { + if msg.To == nil { + r2bcast[i] = msg + } else { + for _, to := range msg.To { + r2p2p[to.Index][i] = msg + } + } + } + r2p2p[i][i] = states[i].ExportR2P2PSelf() + if r2bcast[i] == nil { + r2bcast[i] = states[i].ExportR2BcastSelf() + } + } + + saves := make([]keygen.LocalPartySaveData, n) + for i := 0; i < n; i++ { + out, err := keygen.Round3(states[i], r2p2p[i], r2bcast) + if err != nil { + t.Fatalf("keygen.Round3[%d]: %v", i, err) + } + saves[i] = *out.Save + } + return saves +} diff --git a/tss-lib/eddsa/signing/rounds.go b/tss-lib/eddsa/signing/rounds.go deleted file mode 100644 index 9bc8db1..0000000 --- a/tss-lib/eddsa/signing/rounds.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package signing - -import ( - "errors" - "math/big" - - "github.com/hemilabs/x/tss-lib/v2/common" - "github.com/hemilabs/x/tss-lib/v2/crypto" - "github.com/hemilabs/x/tss-lib/v2/eddsa/keygen" - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -const ( - TaskName = "eddsa-signing" -) - -type ( - base struct { - *tss.Parameters - key *keygen.LocalPartySaveData - data *common.SignatureData - temp *localTempData - out chan<- tss.Message - end chan<- *common.SignatureData - ok []bool // `ok` tracks parties which have been verified by Update() - started bool - number int - } - round1 struct { - *base - } - round2 struct { - *round1 - } - round3 struct { - *round2 - } - finalization struct { - *round3 - } -) - -var ( - _ tss.Round = (*round1)(nil) - _ tss.Round = (*round2)(nil) - _ tss.Round = (*round3)(nil) - _ tss.Round = (*finalization)(nil) -) - -// ----- // - -func (round *base) Params() *tss.Parameters { - return round.Parameters -} - -func (round *base) RoundNumber() int { - return round.number -} - -// CanProceed is inherited by other rounds -func (round *base) CanProceed() bool { - if !round.started { - return false - } - for _, ok := range round.ok { - if !ok { - return false - } - } - return true -} - -// WaitingFor is called by a Party for reporting back to the caller -func (round *base) WaitingFor() []*tss.PartyID { - Ps := round.Parties().IDs() - ids := make([]*tss.PartyID, 0, len(round.ok)) - for j, ok := range round.ok { - if ok { - continue - } - ids = append(ids, Ps[j]) - } - return ids -} - -func (round *base) WrapError(err error, culprits ...*tss.PartyID) *tss.Error { - return tss.NewError(err, TaskName, round.number, round.PartyID(), culprits...) -} - -// ----- // - -// `ok` tracks parties which have been verified by Update() -func (round *base) resetOK() { - for j := range round.ok { - round.ok[j] = false - } -} - -// get ssid from local params -func (round *base) getSSID() ([]byte, error) { - ssidList := []*big.Int{round.EC().Params().P, round.EC().Params().N, round.EC().Params().Gx, round.EC().Params().Gy} // ec curve - ssidList = append(ssidList, round.Parties().IDs().Keys()...) // parties - BigXjList, err := crypto.FlattenECPoints(round.key.BigXj) - if err != nil { - return nil, round.WrapError(errors.New("read BigXj failed"), round.PartyID()) - } - ssidList = append(ssidList, BigXjList...) // BigXj - ssidList = append(ssidList, big.NewInt(int64(round.number))) // round number - ssidList = append(ssidList, round.temp.ssidNonce) - ssid := common.SHA512_256i(ssidList...).Bytes() - - return ssid, nil -} diff --git a/tss-lib/eddsa/signing/types.go b/tss-lib/eddsa/signing/types.go new file mode 100644 index 0000000..323d199 --- /dev/null +++ b/tss-lib/eddsa/signing/types.go @@ -0,0 +1,64 @@ +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + + "github.com/hemilabs/x/tss-lib/v3/eddsa/keygen" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +// TaskName identifies the EdDSA signing protocol in error messages. +const TaskName = "eddsa-signing" + +type localTempData struct { + localMessageStore + + ssidNonce *big.Int + ssid []byte + + // round 1 + wi *big.Int + ri *big.Int + pointRi interface{} // *crypto.ECPoint + deCommit []*big.Int + cjs []*big.Int + + // round 3 + si *big.Int + r *big.Int + m *big.Int + fullBytesLen int +} + +type localMessageStore struct { + signRound1Messages []*tss.Message + signRound2Messages []*tss.Message + signRound3Messages []*tss.Message +} + +// SignatureData holds the final EdDSA signature components. +type SignatureData struct { + Signature []byte // 64-byte R||S + R []byte + S []byte + M []byte +} + +// SigningState holds mutable state across all signing rounds. +type SigningState struct { + params *tss.Parameters + key *keygen.LocalPartySaveData + data *SignatureData + temp localTempData +} + +// SignRoundOutput is returned by each round function. +type SignRoundOutput struct { + Messages []*tss.Message + Signature *SignatureData +} diff --git a/tss-lib/eddsa/signing/utils.go b/tss-lib/eddsa/signing/utils.go index 77a249c..79f9223 100644 --- a/tss-lib/eddsa/signing/utils.go +++ b/tss-lib/eddsa/signing/utils.go @@ -1,33 +1,19 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package signing import ( - "crypto/elliptic" - "io" "math/big" - - "github.com/binance-chain/edwards25519" - - "github.com/hemilabs/x/tss-lib/v2/common" ) func encodedBytesToBigInt(s *[32]byte) *big.Int { - // Use a copy so we don't screw up our original - // memory. sCopy := new([32]byte) - for i := 0; i < 32; i++ { - sCopy[i] = s[i] - } + copy(sCopy[:], s[:]) reverse(sCopy) - - bi := new(big.Int).SetBytes(sCopy[:]) - - return bi + return new(big.Int).SetBytes(sCopy[:]) } func bigIntToEncodedBytes(a *big.Int) *[32]byte { @@ -35,14 +21,8 @@ func bigIntToEncodedBytes(a *big.Int) *[32]byte { if a == nil { return s } - - // Caveat: a can be longer than 32 bytes. s = copyBytes(a.Bytes()) - - // Reverse the byte string --> little endian after - // encoding. reverse(s) - return s } @@ -51,37 +31,30 @@ func copyBytes(aB []byte) *[32]byte { return nil } s := new([32]byte) - - // If we have a short byte string, expand - // it so that it's long enough. + if len(aB) > 32 { + panic("copyBytes: input exceeds 32 bytes, would silently truncate") + } aBLen := len(aB) if aBLen < 32 { diff := 32 - aBLen - for i := 0; i < diff; i++ { - aB = append([]byte{0x00}, aB...) - } - } - - for i := 0; i < 32; i++ { - s[i] = aB[i] + padded := make([]byte, 32) + copy(padded[diff:], aB) + aB = padded } - + copy(s[:], aB) return s } +// ecPointToEncodedBytes produces the Ed25519-format compressed encoding: +// y coordinate in little-endian with the sign bit of x in the top bit +// of byte 31. The "sign" of x in Ed25519 is x mod 2 (the low bit). func ecPointToEncodedBytes(x *big.Int, y *big.Int) *[32]byte { s := bigIntToEncodedBytes(y) - xB := bigIntToEncodedBytes(x) - xFE := new(edwards25519.FieldElement) - edwards25519.FeFromBytes(xFE, xB) - isNegative := edwards25519.FeIsNegative(xFE) == 1 - - if isNegative { + if x.Bit(0) == 1 { s[31] |= (1 << 7) } else { s[31] &^= (1 << 7) } - return s } @@ -91,39 +64,20 @@ func reverse(s *[32]byte) { } } -func addExtendedElements(p, q edwards25519.ExtendedGroupElement) edwards25519.ExtendedGroupElement { - var r edwards25519.CompletedGroupElement - var qCached edwards25519.CachedGroupElement - q.ToCached(&qCached) - edwards25519.GeAdd(&r, &p, &qCached) - var result edwards25519.ExtendedGroupElement - r.ToExtended(&result) - return result +// scReduce reduces a 64-byte little-endian scalar mod the curve order. +func scReduce(in *[64]byte, N *big.Int) *big.Int { + // Convert 64-byte LE to big.Int. + buf := make([]byte, 64) + copy(buf, in[:]) + for i, j := 0, 63; i < j; i, j = i+1, j-1 { + buf[i], buf[j] = buf[j], buf[i] + } + return new(big.Int).Mod(new(big.Int).SetBytes(buf), N) } -func ecPointToExtendedElement(ec elliptic.Curve, x *big.Int, y *big.Int, rand io.Reader) edwards25519.ExtendedGroupElement { - encodedXBytes := bigIntToEncodedBytes(x) - encodedYBytes := bigIntToEncodedBytes(y) - - z := common.GetRandomPositiveInt(rand, ec.Params().N) - encodedZBytes := bigIntToEncodedBytes(z) - - var fx, fy, fxy edwards25519.FieldElement - edwards25519.FeFromBytes(&fx, encodedXBytes) - edwards25519.FeFromBytes(&fy, encodedYBytes) - - var X, Y, Z, T edwards25519.FieldElement - edwards25519.FeFromBytes(&Z, encodedZBytes) - - edwards25519.FeMul(&X, &fx, &Z) - edwards25519.FeMul(&Y, &fy, &Z) - edwards25519.FeMul(&fxy, &fx, &fy) - edwards25519.FeMul(&T, &fxy, &Z) - - return edwards25519.ExtendedGroupElement{ - X: X, - Y: Y, - Z: Z, - T: T, - } +// scMulAdd computes (a*b + c) mod N. +func scMulAdd(a, b, c, N *big.Int) *big.Int { + ab := new(big.Int).Mul(a, b) + ab.Add(ab, c) + return ab.Mod(ab, N) } diff --git a/tss-lib/eddsa/signing/validate_test.go b/tss-lib/eddsa/signing/validate_test.go new file mode 100644 index 0000000..9c9dd71 --- /dev/null +++ b/tss-lib/eddsa/signing/validate_test.go @@ -0,0 +1,97 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package signing + +import ( + "math/big" + "testing" + + "github.com/hemilabs/x/tss-lib/v3/crypto" + cmt "github.com/hemilabs/x/tss-lib/v3/crypto/commitments" + "github.com/hemilabs/x/tss-lib/v3/crypto/schnorr" + "github.com/hemilabs/x/tss-lib/v3/tss" +) + +func TestSignRound2MessageValidateBasic(t *testing.T) { + if (*SignRound2Message)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&SignRound2Message{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + ec := tss.Edwards() + alpha := crypto.ScalarBaseMult(ec, big.NewInt(7)) + proof := &schnorr.ZKProof{Alpha: alpha, T: big.NewInt(99)} + if !(&SignRound2Message{ + DeCommitment: cmt.HashDeCommitment{big.NewInt(1), big.NewInt(2)}, + ZKProof: proof, + }).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestSignRound3MessageValidateBasic(t *testing.T) { + if (*SignRound3Message)(nil).ValidateBasic() { + t.Fatal("nil should fail") + } + if (&SignRound3Message{}).ValidateBasic() { + t.Fatal("zero-value should fail") + } + if !(&SignRound3Message{S: big.NewInt(42)}).ValidateBasic() { + t.Fatal("valid should pass") + } +} + +func TestBigIntToEncodedBytesNil(t *testing.T) { + result := bigIntToEncodedBytes(nil) + if result == nil { + t.Fatal("nil input should return zero bytes, not nil") + } + for _, b := range result { + if b != 0 { + t.Fatal("nil input should produce all zeros") + } + } +} + +func TestCopyBytesNil(t *testing.T) { + if copyBytes(nil) != nil { + t.Fatal("nil input should return nil") + } +} + +func TestCopyBytesTooLong(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("should panic on > 32 bytes") + } + }() + copyBytes(make([]byte, 33)) +} + +func TestPrepareForSigningPanics(t *testing.T) { + ec := tss.Edwards() + N := ec.Params().N + + t.Run("len mismatch", func(t *testing.T) { + defer func() { _ = recover() }() + PrepareForSigning(ec, 0, 3, big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(2)}) + t.Fatal("should panic") + }) + + t.Run("i out of range", func(t *testing.T) { + defer func() { _ = recover() }() + PrepareForSigning(ec, 5, 3, big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}) + t.Fatal("should panic") + }) + + t.Run("equal keys", func(t *testing.T) { + defer func() { _ = recover() }() + PrepareForSigning(ec, 0, 2, big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(1)}) + t.Fatal("should panic") + }) + + _ = N +} diff --git a/tss-lib/go.mod b/tss-lib/go.mod index 5ec8704..91a9ada 100644 --- a/tss-lib/go.mod +++ b/tss-lib/go.mod @@ -1,10 +1,8 @@ -module github.com/hemilabs/x/tss-lib/v2 +module github.com/hemilabs/x/tss-lib/v3 -go 1.16 +go 1.25 require ( - github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43 - github.com/btcsuite/btcd v0.23.4 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcutil v1.0.2 github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3 @@ -12,7 +10,17 @@ require ( github.com/ipfs/go-log v1.0.5 github.com/otiai10/primes v0.0.0-20210501021515-f1b2be525a11 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.13.0 - google.golang.org/protobuf v1.31.0 +) + +require ( + github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/ipfs/go-log/v2 v2.1.3 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.16.0 // indirect ) diff --git a/tss-lib/go.sum b/tss-lib/go.sum index aa22dc6..385e393 100644 --- a/tss-lib/go.sum +++ b/tss-lib/go.sum @@ -3,30 +3,16 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= -github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43 h1:Vkf7rtHx8uHx8gDfkQaCdVfc+gfrF9v6sR6xJy7RXNg= -github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43/go.mod h1:TnVqVdGEK8b6erOMkcyYGWzCQMw7HEMCOw3BgFYCFWs= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= -github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= -github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -39,25 +25,10 @@ github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3 h1:l/lhv2aJCUignzls81+wvga0TFlyoZ github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3/go.mod h1:AKpV6+wZ2MfPRJnTbQ6NPgWrKzbe9RCIlCF/FKzMtM8= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -69,25 +40,16 @@ github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JP github.com/ipfs/go-log/v2 v2.1.3 h1:1iS3IU7aXRlbgUpN8yTTpJ53NXYjAe37vcI5+5nYrzk= github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -107,20 +69,13 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -136,66 +91,30 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -203,36 +122,21 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= diff --git a/tss-lib/protob/ecdsa-keygen.proto b/tss-lib/protob/ecdsa-keygen.proto deleted file mode 100644 index 249da90..0000000 --- a/tss-lib/protob/ecdsa-keygen.proto +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib.ecdsa.keygen; -option go_package = "ecdsa/keygen"; - -/* - * Represents a BROADCAST message sent during Round 1 of the ECDSA TSS keygen protocol. - */ -message KGRound1Message { - bytes commitment = 1; - bytes paillier_n = 2; - bytes n_tilde = 3; - bytes h1 = 4; - bytes h2 = 5; - repeated bytes dlnproof_1 = 6; - repeated bytes dlnproof_2 = 7; -} - -/* - * Represents a P2P message sent to each party during Round 2 of the ECDSA TSS keygen protocol. - */ -message KGRound2Message1 { - bytes share = 1; - repeated bytes facProof = 2; -} - -/* - * Represents a BROADCAST message sent to each party during Round 2 of the ECDSA TSS keygen protocol. - */ -message KGRound2Message2 { - repeated bytes de_commitment = 1; - repeated bytes modProof = 2; -} - -/* - * Represents a BROADCAST message sent to each party during Round 3 of the ECDSA TSS keygen protocol. - */ -message KGRound3Message { - repeated bytes paillier_proof = 1; -} diff --git a/tss-lib/protob/ecdsa-resharing.proto b/tss-lib/protob/ecdsa-resharing.proto deleted file mode 100644 index d19b7fc..0000000 --- a/tss-lib/protob/ecdsa-resharing.proto +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib.ecdsa.resharing; -option go_package = "ecdsa/resharing"; - -/* - * The Round 1 data is broadcast to peers of the New Committee in this message. - */ -message DGRound1Message { - bytes ecdsa_pub_x = 1; - bytes ecdsa_pub_y = 2; - bytes v_commitment = 3; - bytes ssid = 4; -} - -/* - * The Round 2 data is broadcast to other peers of the New Committee in this message. - */ -message DGRound2Message1 { - bytes paillier_n = 1; - repeated bytes modProof = 2; - bytes n_tilde = 3; - bytes h1 = 4; - bytes h2 = 5; - repeated bytes dlnproof_1 = 6; - repeated bytes dlnproof_2 = 7; -} - -/* - * The Round 2 "ACK" is broadcast to peers of the Old Committee in this message. - */ -message DGRound2Message2 { -} - -/* - * The Round 3 data is sent to peers of the New Committee in this message. - */ -message DGRound3Message1 { - bytes share = 1; -} - -/* - * The Round 3 data is broadcast to peers of the New Committee in this message. - */ -message DGRound3Message2 { - repeated bytes v_decommitment = 1; -} - -/* - * The Round 4 "ACK" is broadcast to peers of the Old and New Committees from the New Committee in this message. - */ -message DGRound4Message2 { -} - -/* - * The Round 4 message to peers of New Committees from the New Committee in this message. - */ -message DGRound4Message1 { - repeated bytes facProof = 1; -} \ No newline at end of file diff --git a/tss-lib/protob/ecdsa-signing.proto b/tss-lib/protob/ecdsa-signing.proto deleted file mode 100644 index 08591c0..0000000 --- a/tss-lib/protob/ecdsa-signing.proto +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib.ecdsa.signing; -option go_package = "ecdsa/signing"; - -/* - * Represents a P2P message sent to each party during Round 1 of the ECDSA TSS signing protocol. - */ -message SignRound1Message1 { - bytes c = 1; - repeated bytes range_proof_alice = 2; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 1 of the ECDSA TSS signing protocol. - */ -message SignRound1Message2 { - bytes commitment = 1; -} - -/* - * Represents a P2P message sent to each party during Round 2 of the ECDSA TSS signing protocol. - */ -message SignRound2Message { - bytes c1 = 1; - bytes c2 = 2; - repeated bytes proof_bob = 3; - repeated bytes proof_bob_wc = 4; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 3 of the ECDSA TSS signing protocol. - */ -message SignRound3Message { - bytes theta = 1; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 4 of the ECDSA TSS signing protocol. - */ -message SignRound4Message { - repeated bytes de_commitment = 1; - bytes proof_alpha_x = 2; - bytes proof_alpha_y = 3; - bytes proof_t = 4; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 5 of the ECDSA TSS signing protocol. - */ -message SignRound5Message { - bytes commitment = 1; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 6 of the ECDSA TSS signing protocol. - */ -message SignRound6Message { - repeated bytes de_commitment = 1; - bytes proof_alpha_x = 2; - bytes proof_alpha_y = 3; - bytes proof_t = 4; - bytes v_proof_alpha_x = 5; - bytes v_proof_alpha_y = 6; - bytes v_proof_t = 7; - bytes v_proof_u = 8; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 7 of the ECDSA TSS signing protocol. - */ -message SignRound7Message { - bytes commitment = 1; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 8 of the ECDSA TSS signing protocol. - */ -message SignRound8Message { - repeated bytes de_commitment = 1; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 9 of the ECDSA TSS signing protocol. - */ -message SignRound9Message { - bytes s = 1; -} diff --git a/tss-lib/protob/eddsa-keygen.proto b/tss-lib/protob/eddsa-keygen.proto deleted file mode 100644 index 199d050..0000000 --- a/tss-lib/protob/eddsa-keygen.proto +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib.eddsa.keygen; -option go_package = "eddsa/keygen"; - -/* - * Represents a BROADCAST message sent during Round 1 of the EDDSA TSS keygen protocol. - */ -message KGRound1Message { - bytes commitment = 1; -} - -/* - * Represents a P2P message sent to each party during Round 2 of the EDDSA TSS keygen protocol. - */ -message KGRound2Message1 { - bytes share = 1; -} - -/* - * Represents a BROADCAST message sent to each party during Round 2 of the EDDSA TSS keygen protocol. - */ -message KGRound2Message2 { - repeated bytes de_commitment = 1; - bytes proof_alpha_x = 2; - bytes proof_alpha_y = 3; - bytes proof_t = 4; -} diff --git a/tss-lib/protob/eddsa-resharing.proto b/tss-lib/protob/eddsa-resharing.proto deleted file mode 100644 index 3b646cb..0000000 --- a/tss-lib/protob/eddsa-resharing.proto +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib.eddsa.resharing; -option go_package = "eddsa/resharing"; - -/* - * The Round 1 data is broadcast to peers of the New Committee in this message. - */ -message DGRound1Message { - bytes eddsa_pub_x = 1; - bytes eddsa_pub_y = 2; - bytes v_commitment = 3; -} - -/* - * The Round 2 "ACK" is broadcast to peers of the Old Committee in this message. - */ -message DGRound2Message { -} - -/* - * The Round 3 data is sent to peers of the New Committee in this message. - */ -message DGRound3Message1 { - bytes share = 1; -} - -/* - * The Round 3 data is broadcast to peers of the New Committee in this message. - */ -message DGRound3Message2 { - repeated bytes v_decommitment = 1; -} - -/* - * The Round 4 "ACK" is broadcast to peers of the Old and New Committees from the New Committee in this message. - */ -message DGRound4Message { -} diff --git a/tss-lib/protob/eddsa-signing.proto b/tss-lib/protob/eddsa-signing.proto deleted file mode 100644 index b018279..0000000 --- a/tss-lib/protob/eddsa-signing.proto +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib.eddsa.signing; -option go_package = "eddsa/signing"; - -/* - * Represents a BROADCAST message sent to all parties during Round 1 of the EDDSA TSS signing protocol. - */ -message SignRound1Message { - bytes commitment = 1; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 2 of the EDDSA TSS signing protocol. - */ -message SignRound2Message { - repeated bytes de_commitment = 1; - bytes proof_alpha_x = 2; - bytes proof_alpha_y = 3; - bytes proof_t = 4; -} - -/* - * Represents a BROADCAST message sent to all parties during Round 3 of the EDDSA TSS signing protocol. - */ -message SignRound3Message { - bytes s = 1; -} diff --git a/tss-lib/protob/message.proto b/tss-lib/protob/message.proto deleted file mode 100644 index 707bf03..0000000 --- a/tss-lib/protob/message.proto +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; -package binance.tsslib; -option go_package = "./tss"; - -import "google/protobuf/any.proto"; - -/* - * Wrapper for TSS messages, often read by the transport layer and not itself sent over the wire - */ -message MessageWrapper { - // PartyID represents a participant in the TSS protocol rounds. - // Note: The `id` and `moniker` are provided for convenience to allow you to track participants easier. - // The `id` is intended to be a unique string representation of `key` and `moniker` can be anything (even left blank). - message PartyID { - string id = 1; - string moniker = 2; - bytes key = 3; - } - - // Metadata optionally un-marshalled and used by the transport to route this message. - bool is_broadcast = 1; - // Metadata optionally un-marshalled and used by the transport to route this message. - bool is_to_old_committee = 2; // used only in certain resharing messages - // Metadata optionally un-marshalled and used by the transport to route this message. - bool is_to_old_and_new_committees = 5; // used only in certain resharing messages - - // Metadata optionally un-marshalled and used by the transport to route this message. - PartyID from = 3; - // Metadata optionally un-marshalled and used by the transport to route this message. - repeated PartyID to = 4; - - // This field is actually what is sent through the wire and consumed on the other end by UpdateFromBytes. - // An Any contains an arbitrary serialized message as bytes, along with a URL that - // acts as a globally unique identifier for and resolves to that message's type. - google.protobuf.Any message = 10; -} diff --git a/tss-lib/protob/signature.proto b/tss-lib/protob/signature.proto deleted file mode 100644 index a7aeeaa..0000000 --- a/tss-lib/protob/signature.proto +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -syntax = "proto3"; - -package binance.tsslib; -option go_package = "./common"; - -/* - * Container for output signatures, mostly used for marshalling this data structure to a mobile app - */ -message SignatureData { - bytes signature = 1; - - // Ethereum-style recovery byte; only the first byte is relevant - bytes signature_recovery = 2; - - // Signature components R, S - bytes r = 3; - bytes s = 4; - - // M represents the original message digest that was signed M - bytes m = 5; -} diff --git a/tss-lib/test/_ecdsa_fixtures/keygen_data_0.json b/tss-lib/test/_ecdsa_fixtures/keygen_data_0.json deleted file mode 100644 index 42e7d0b..0000000 --- a/tss-lib/test/_ecdsa_fixtures/keygen_data_0.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "PaillierSK": { - "N": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185392600641669797286300834348740665304662829760721139573070204170902129262797162145018079946053388917283347495995703735479819366865064178966988962612678607190805087224162314010583832802161588455461100682306289046720947974174001828045869589748392310605782826097558345479795972515955139600004112610785604729710757, - "LambdaN": 13431085295690593058572319560900453855810720555347492953036549746552112129315998808168729942174524157718324799297383106393095124569860271493420818894683544875947873401184032052057831494025649221552832761274521811684044390878699906153121026338481580823689210731716406885837799443608773893711130597469936261592532213858878816794879138507493230952759071143256763914863135847264553077488577664633510002801989144150002815082601970607292530318876745886925922476991203656094267047307176836180759972736598187277189369375666238571075693265319527847455818556610107935217778613614515276483294115793052848151350340343144475494998, - "PhiN": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185064427717757633589758277014986461905518142286513527829726271694529106154977155329267020005603978288300005630165203941214585060637753491773851844953982407312188534094614353672361519945473196374554378738751332477142151386530639055694911637113220215870435557227229030552966588231586105696302700680686288950989996, - "P": 156199992157527515679277851563515941446129352347011319825196067672572313106672920497393870514107469203466250029881858883814872913259387909227911821518374527804663005734804760515923302853633171490096548012329974306537954808287455990519023653082720419807513617030697689651815046731746603871834526414575616974279, - "Q": 171972931754636180863279482190687457698558121860600423518736408700450794713333895253666069935303159779875615800617935381419433314051299283909205837177825350811890123813155577706389553834758909416625395542626595272258632835075316360438928982089374315539755253298617237177569237637287299829577403684740161746483 - }, - "NTildei": 25107490776052945575790163886980744121852075793230702092031092910315419013111724585107741342302647097816029689069156500419649067226989207335403141846585589456214707140363806918024254341805807847344462552372749802373561411623464018306841140152736878126807643286464707464144491205717529334857128642937311664356950670200785184493082292988908234459722618881044613550904554507333793627844968327344517418351075665978629614435510466378211576459017353838583039397930178040557511540818370302033808216608330168909665648805527673068950251148153088673193641290377199021831923470431364077200419352774733381328839199321622201645277, - "H1i": 947268510305326446073634507724913447936734171636912400557401318775427643035322780043344044871778218536295489345747992085537349997385753459769909944243608187249295932620582767525243046024431872134558350124222211815956076009495579000118546531817489783543950708796804986346442485595844139040615169351977594594085460608932273701244091036215057114383266995365365226626217411088112095883376367775475107954293975266374705057036496941779873360807750450088301028537780564210964889218799820623451941121168857520561736570209171665676631521362739174866629364755585577716299287494251706261472512421959632149833106509542229972234, - "H2i": 369382535766024782757053511943484023707590301248858510505619543451105355366349475321600848828578055383112252081262740450957242693258711711573898608872557215737850380375149487180022863563616178163440683814662347260503803753150609907077552201623376131096249150783552367189222999632342102603491398593162398739317344334427947844029843540621897547082716967267285286086227255034044222917612280937408214149645699005643727644027239999997789724357422423935120674874708262799420509411969660535187315093553065000790565517535769427338692918882249946664488170641583406635227373502217028982923125561321182147198392699754510926843, - "Alpha": 6669702575802332067051507400723122644839122909837745212967242092483177093666409546803836461769838120342268901353955156661858215357972959560589013601496347059806025103870404243017483236835513779152636288855166974055130846382972514018626781368599584594970808367427466242387093516189696228727421743052639556770083365914732684526264745234552992519722018618668212942788843125095288624719491808726320606573330293693883472896837701226592981135230240346758366425506314368382164046393267850565316732719649541361696315531259629023604214612386322746665953174348707199467021358068970739744717116080568232157794570566194767962193, - "Beta": 4226702103283230409689887623397868172263773072284894957823563643849293193454026723702667572204652313053676186724572803175380434781233229139441124649381910161179586223174332599144926974124401757990737042528978346870480691970515558734832577382199462271326295128038175934801169919909683367743160668157108777692509546415310274417808611190360269418302199996410620600891919468677526911530111335678118505332265820985238717612050499504379017017998849335196637255127847818529939710513362492159636375161860102767812483118583893111980078668274650612227857015281800001652750733997357414494554663009577159114465037019654992649831, - "P": 73458738483859906960505530286009984246470949380903088699714197960661061085155739592774719387578463149575507386969755941321227590452894174208881731929135833875986292699119509529479934647644869851989583450086833987908020203092806374228228193163809755370417640606181205095011955590840300054963158041301552101041, - "Q": 85447597162213295592421685633760432054265215569039633105172607001373470153249654026667908067025680307951469974169784414915998293227135302230856861321307857553984952411841792538464994439156606764727476914663543473228913738927277839435079606623601328422838494376915981928356488990978178935974751052976368228959, - "Xi": 11916527433647828918977250606530964748554479545005979893012447833077873661340, - "ShareID": 59857031556462284717113645237935722663924232558699039874171440941840562677323, - "Ks": [ - 59857031556462284717113645237935722663924232558699039874171440941840562677323, - 59857031556462284717113645237935722663924232558699039874171440941840562677324, - 59857031556462284717113645237935722663924232558699039874171440941840562677325, - 59857031556462284717113645237935722663924232558699039874171440941840562677326, - 59857031556462284717113645237935722663924232558699039874171440941840562677327 - ], - "NTildej": [ - 25107490776052945575790163886980744121852075793230702092031092910315419013111724585107741342302647097816029689069156500419649067226989207335403141846585589456214707140363806918024254341805807847344462552372749802373561411623464018306841140152736878126807643286464707464144491205717529334857128642937311664356950670200785184493082292988908234459722618881044613550904554507333793627844968327344517418351075665978629614435510466378211576459017353838583039397930178040557511540818370302033808216608330168909665648805527673068950251148153088673193641290377199021831923470431364077200419352774733381328839199321622201645277, - 25347321253130040165669198464747637594561084543160875890419030859255281770152898118930416834987900972848102624649324216864737441361174703716495863609322476087408028387965233238285802668149470294745292681572931725456001393301305606431470624857854001369500295623909754190673037775702216922020351830224578270444039819022050738946522292544390839130641700344286132805509002888252787493089063466842186838763536749516490621525613122365080892293964923531037888659136998882617232588657938236946761539565880695421135081565601958037809654399412376843665230604400657963765839300124472222517361299084266084873325229770349534163801, - 21292308023632581181198289513256444712308177801737936647775817904740223548406904422170044682275257431431315028868812996459652895591102638516259762883465973519952131280804384814232387700680465986308431924126707276653911414520068641511680988816011871501850341616042836704357314055609697319128691732749390230733118584785117859207288385865822542643892497962395263780902218346962474333143560514409678469862250207440675303576178809488957082804485944446225032956319749038833642485681946267959990181650810435723731755627693490958402541015772649403218387116342415453965710612578891122860080475980560084488514089712934013739781, - 30862742439593241585708940738147962226366718050501165321237842572436669411737554224118298772517486812375362296405238805912443683584456437953738131350045938787466841040220797401584428446174730486886913719857484102733725336155131475996004306581440515141136345274453183481082707684162136893963291137234740111704738897973555849945611157507740799100242851006495725457213328987753002399448999330977114104566617308036743409045315165685308303262653843118404666538923863063081603256452671995759383632696290823794779551389200638930288120410329395673124242908818519519330118489440718827371013019585524024323106350150372893461689, - 22979378405138893589556133897521754683725883868866200124855036635451629318130978502381364148180090802113404290988890710862982965215323041776178270890557477521858892737028622171038670089616608354902721183960978083779850093600290031995183687729693685221986115197995396115379213021683786733329612441286209467155931087319154615773299643384467163395079212511182788668809520330816917834693871112365384301753056859879036141250397887546537837356226101620007886380291232478721279115321079877121757818532329118011682430897866452653899829996834157870634757693124417404439069108796004756126487268680259509658734527559041787231993 - ], - "H1j": [ - 947268510305326446073634507724913447936734171636912400557401318775427643035322780043344044871778218536295489345747992085537349997385753459769909944243608187249295932620582767525243046024431872134558350124222211815956076009495579000118546531817489783543950708796804986346442485595844139040615169351977594594085460608932273701244091036215057114383266995365365226626217411088112095883376367775475107954293975266374705057036496941779873360807750450088301028537780564210964889218799820623451941121168857520561736570209171665676631521362739174866629364755585577716299287494251706261472512421959632149833106509542229972234, - 3880611998802971481733631912608098494196262778323132826239497201888814778206565779038508295122457059564658474446013387570155222804192995563846151508944721213706421845709980882611956739258515443677158361364276786837940404625680574358803765552923094221476122072037719326145018613827892918963555625064867923347247217043400958580189757825375746004023039968242295816205605839011845166061436412284630990719600784460170159747697580968014664501419463157750169639809058771175198577548493272625218114926414363501638734650889306046401503137104184980837461670247903219705017626260602184962369771097797399062562513353217770565531, - 10831225843690707396172531846155417775408096606230693395561759792282094678514600816663347869748948927505461627250570771469119140533266318664691242702922064589002187370016461932692821183944924214028723777910582605988927471997349297521445102656640882914313554019001846714781268540993241638422699989309757114468372538565383360692272346876551928106077801669528247179220120217249637229522616724754257258083101113512544707361337883525289735840725085893321825199206160881032044949147621462286088226618153585859120352649591156109044603116965314576319186213041333237791389005373191075396808136402252420638572954706343475908070, - 7379047495513012741768052948709028575585555485999633742902872635999567523931496397934138722681164927896829567152505037328183413349521525062101059035871423959216606865846805649228889409341121623645276995775466833580910793875325853108618331288089921648034916011339650914136927737993536151052450142994995957064434847339676185441357826456108823451579572271337009853306909251138234707237745952438799718674765118984490163866366131359672038740868456547662412411582409607895270049993194846640187000629665900662666631953358892682510778724505052220510687061629914270273761091793976303803161711621832014373503323366016634630406, - 11181628178709225486839172762330742659423724114653226835819397085381257304105257566937592702765853135360490266257083192830870077666275960663723976086310235934350572650480643691450656438652769853018111519504498965737440967647717818784480763727200258889702626069322469743838822112397983393755250519010298110374742466783922925487057158527359106287066137656141433380846258646250390469229071336860949790965072334352962521185854509550842351266605524163986806331802767702307634084162000820507840777885400805512071448246749124225768822589052733208381949931869152348048701648349767479285228581634453249080578720203097097514457 - ], - "H2j": [ - 369382535766024782757053511943484023707590301248858510505619543451105355366349475321600848828578055383112252081262740450957242693258711711573898608872557215737850380375149487180022863563616178163440683814662347260503803753150609907077552201623376131096249150783552367189222999632342102603491398593162398739317344334427947844029843540621897547082716967267285286086227255034044222917612280937408214149645699005643727644027239999997789724357422423935120674874708262799420509411969660535187315093553065000790565517535769427338692918882249946664488170641583406635227373502217028982923125561321182147198392699754510926843, - 15969079226966183502382475788401338523488393107499291032002044296474627394217596503568693748659928310923714663501210832583018731196547300812154979725769686288361401778491755680431944887852103221593745623856378860738388368922715577130878948380171217565406616753411777571011139446871620361320986832525400727639941640937364793530207582464684574638726091525574744197708378588020682070096454926012197394347212926657909811288708691651092564968341401161265195710381753419063864921935963903871011102644256286369641306466313805437318014970058871604639507243703932226939038829663830985880788590281053591951619664726739953671018, - 4991965837400033768069871541004261063135140339060316531025599789490182217840042887067892359235887756385798984623237629620830856274859128458536333773291056510054624668039972342087961925191332459597054733496082441434562377800869508105363637144128472861641912914050632826421706717769073047295100882343425757237060029497292934794235607113222710491355298594636899811931946648047811854321545995037508110462735244536402582555614331492107887985617810756386029525697146027973237905139754077084275404126435090136074550061845235250362605148173730041087342012184590101575852114035899339078096801167678750962125251280492197772961, - 23064781826724373162059309790268929175652024853806919970585039362565178134882146726172590403276064143405780341854075186376431326467367967581674319153076910116152907650926195389275015857432169732825486479963071595528043281158690951801576413614814760292960443710324174730418861380180819802157714395735784311928236401433597447641321165573011917942945482934111736905171027083754748263370419119297225245442731766002872688005764140266867116940180286239156118891196076208004108028110204585118322786319227036687507415330523815192275901354672284703528348057050369197376684323825935099945673108591425248965307506340817771591441, - 11624783050789373146135145081851167787144912685550655481254753886486876945039110175782945406523699017594888407389014880101840909734903251718897005090801524812985842948051908677768943122267838594824514706829210878634123695856103833890298708489700110861686115821849284312876390414092087922712380944749991516509300532655840012200292315982914838173353675847647411050340787544373391445319951232858137394531780600427092367231102522845204917484802409447548360146964783744378214393625590646132406343132441415352603518333034984771651345199420810327304168670235976704426708270671344968176457707557409261114405916868900751036145 - ], - "BigXj": [ - { - "Curve": "secp256k1", - "Coords": [ - 95225479287625109140551300097635441933915975782583911515343531112654602880814, - 113745830257261593369068705146261698861441809650110061237310141136031506190085 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 19909020077923456087962021369246692987785610885502332606764981730113023110067, - 60076350170225224442893367050676875983156697199114782416705437692213004111433 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15656029217860558075932288367874977299995954233140419375302609508233656030817, - 88293512119423239639079954683198441748713533855873639211876694257553830935691 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15825259379483050804368543653451724857970141958098760943464945060863314262898, - 46510254063758718632499733093297318465018983961512441577134679077369278627011 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 101163968142129288084264305494084191253074413300747651525777392366080313581620, - 19458713537429380315587854195885123660811710862685360770347430223563133437479 - ] - } - ], - "PaillierPKs": [ - { - "N": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185392600641669797286300834348740665304662829760721139573070204170902129262797162145018079946053388917283347495995703735479819366865064178966988962612678607190805087224162314010583832802161588455461100682306289046720947974174001828045869589748392310605782826097558345479795972515955139600004112610785604729710757 - }, - { - "N": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654571826800302294766234904003147622246551178854009373086133349568572584906962173774282191211244583738166117722131851467394725949126097483624199330170392292115956857647929895014719727669500452359666570376448590229755339126098108084513655351630004806845329610086536348250655270492083872210115099541350980087869489 - }, - { - "N": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114362935636941751781265771147161683942488081675636897258681038605775448214108367751993197065197897191643383564344845162403884453232776839031251175853763144050201714908798915379664014184087913029794762586324582687266708240565299184055542301695610690632283322864399949456272972805575542427101734659832898527078677 - }, - { - "N": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483556240372784852668293634144857453177818024665828049715609921864852313661181061967825839048394234894185931968992541576874445544364635775263264674967563604397356712492758200667296917972566268326712277912968541425534456091226445588857731271210711997226828598037017820056231841183710665446107873358077925757871906777 - }, - { - "N": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811976260936406546600112652090553738417255733994944221554428167638466246670287061019896463881779810197390238307556892485807795138448959345532929528137209046373349550262355661974463926686395148775662060236988349400478971416621513539908477667503550115870803074998306032371456267566517610267867391193312424397935929 - } - ], - "ECDSAPub": { - "Curve": "secp256k1", - "Coords": [ - 76266489189895419469020567248501927603989841769205411177925179985114092514949, - 17959638069442050620236663888410692330316152082152911789514411031446499229348 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_ecdsa_fixtures/keygen_data_1.json b/tss-lib/test/_ecdsa_fixtures/keygen_data_1.json deleted file mode 100644 index 3e12a3b..0000000 --- a/tss-lib/test/_ecdsa_fixtures/keygen_data_1.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "PaillierSK": { - "N": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654571826800302294766234904003147622246551178854009373086133349568572584906962173774282191211244583738166117722131851467394725949126097483624199330170392292115956857647929895014719727669500452359666570376448590229755339126098108084513655351630004806845329610086536348250655270492083872210115099541350980087869489, - "LambdaN": 14284713468954906580408426295487163091199353591603281890078744654139905931688046954110605951852759352282674036331595951918171817749545989577036170710370838406865010435508019846701803704731459562515686033477275104175064987070110491849032196670475965353481213507648788824218800532084424167082421055705448481327116571621783280156627266306673613557770132415067791761025356248059645897264585788635046339329639753214021614915782754214179908727166288405568041736300150892127323291788850009844614304509270438683742045888904656839139941936906942558425724970581335889893630058987401037228149733076112847409338010564314966102162, - "PhiN": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654233143243566560313254532613347227115540264830135583522050712496119291794529171577270092678659279506428043229831565508428359817454332576811136083472600301784254646583577700019689228609018540877367484091777809313678279883873813885116851449941162671779787260117974802074456299466152225694818676021128629932204324, - "P": 179696051055123023215556819548680549334277719811328399025475104641756939359631189702474530421876600335876842000086226772970952145746397968678244929383831619212881928505998388309390501861374874325811635591096208662594788934951680613702506047691842619635942634194229436037649059736143528223527514655893104450263, - "Q": 158987505680611429764814570251714581676636304062461165057161967811536173073371007309624002163427631402197650300199732193395179526018508844385001768408158712489329135846196606721108558620536607973274649079684707414464453289342518783101395641150292445906407334367316740161321966195502987072896005566457051214903 - }, - "NTildei": 25347321253130040165669198464747637594561084543160875890419030859255281770152898118930416834987900972848102624649324216864737441361174703716495863609322476087408028387965233238285802668149470294745292681572931725456001393301305606431470624857854001369500295623909754190673037775702216922020351830224578270444039819022050738946522292544390839130641700344286132805509002888252787493089063466842186838763536749516490621525613122365080892293964923531037888659136998882617232588657938236946761539565880695421135081565601958037809654399412376843665230604400657963765839300124472222517361299084266084873325229770349534163801, - "H1i": 3880611998802971481733631912608098494196262778323132826239497201888814778206565779038508295122457059564658474446013387570155222804192995563846151508944721213706421845709980882611956739258515443677158361364276786837940404625680574358803765552923094221476122072037719326145018613827892918963555625064867923347247217043400958580189757825375746004023039968242295816205605839011845166061436412284630990719600784460170159747697580968014664501419463157750169639809058771175198577548493272625218114926414363501638734650889306046401503137104184980837461670247903219705017626260602184962369771097797399062562513353217770565531, - "H2i": 15969079226966183502382475788401338523488393107499291032002044296474627394217596503568693748659928310923714663501210832583018731196547300812154979725769686288361401778491755680431944887852103221593745623856378860738388368922715577130878948380171217565406616753411777571011139446871620361320986832525400727639941640937364793530207582464684574638726091525574744197708378588020682070096454926012197394347212926657909811288708691651092564968341401161265195710381753419063864921935963903871011102644256286369641306466313805437318014970058871604639507243703932226939038829663830985880788590281053591951619664726739953671018, - "Alpha": 21491373657758085577916665593069897304698302824435532374383303720077841245117963656613269831569915553635905663061595834031898972929677249621933525501357436617324598304991585720687960909120658023342943471479838820960047997726786932001492921886802008375343827315954282235777792289696889802892898512843614362177443840425280198612137376280284849353811498082367792976318845774884618722716252884964293120442367038395033342390295633797972152438214316402685935216333012823407451764996594240864085421336823764988704967767076102572703398147213022890269868975034087372976874667029882482262817244173861823337136055042053399964749, - "Beta": 3320311752963954234697711283997815118439358938488190680929864725275034450096946665982937070819528081639621271613538490046386233130458063404579138646139919818379405279730584606243356048610802153043772324355846574025657091426070974316058004074522798849624673902006611228323918313017476418442921878743271314304960386902920541720359376856180397105402483065699785280311003389761147901974764578633793149569955286297534816723552552275416622730320317061458505375678230006930629535752265013560395587064530027550698558348295866795214521021305541919346582881078518616476349467229447131285652277977502561612452907061432958990114, - "P": 70809288826622369725825379006387741309025014873650261751266229233883897190933864780171874016638684817324204969639453339585607590221341667270589678303972956528804192252650177939435179917755571202115955733042695654662128941468586251562467087477332554065966906744871985875266426991185100611501333353651522226181, - "Q": 89491511894694159453747430128734210348570662135726367595285167836164539619537914844620100362327593655844333914098578866199805574792984175111800205197419163387659137071854218603937967776465225847192887789659618586209585295171442059952399265568911468803824806178632700690337945305729670474997622116792123325013, - "Xi": 76948082823091852504553670832408291290543297863564249603348941514219073751559, - "ShareID": 59857031556462284717113645237935722663924232558699039874171440941840562677324, - "Ks": [ - 59857031556462284717113645237935722663924232558699039874171440941840562677323, - 59857031556462284717113645237935722663924232558699039874171440941840562677324, - 59857031556462284717113645237935722663924232558699039874171440941840562677325, - 59857031556462284717113645237935722663924232558699039874171440941840562677326, - 59857031556462284717113645237935722663924232558699039874171440941840562677327 - ], - "NTildej": [ - 25107490776052945575790163886980744121852075793230702092031092910315419013111724585107741342302647097816029689069156500419649067226989207335403141846585589456214707140363806918024254341805807847344462552372749802373561411623464018306841140152736878126807643286464707464144491205717529334857128642937311664356950670200785184493082292988908234459722618881044613550904554507333793627844968327344517418351075665978629614435510466378211576459017353838583039397930178040557511540818370302033808216608330168909665648805527673068950251148153088673193641290377199021831923470431364077200419352774733381328839199321622201645277, - 25347321253130040165669198464747637594561084543160875890419030859255281770152898118930416834987900972848102624649324216864737441361174703716495863609322476087408028387965233238285802668149470294745292681572931725456001393301305606431470624857854001369500295623909754190673037775702216922020351830224578270444039819022050738946522292544390839130641700344286132805509002888252787493089063466842186838763536749516490621525613122365080892293964923531037888659136998882617232588657938236946761539565880695421135081565601958037809654399412376843665230604400657963765839300124472222517361299084266084873325229770349534163801, - 21292308023632581181198289513256444712308177801737936647775817904740223548406904422170044682275257431431315028868812996459652895591102638516259762883465973519952131280804384814232387700680465986308431924126707276653911414520068641511680988816011871501850341616042836704357314055609697319128691732749390230733118584785117859207288385865822542643892497962395263780902218346962474333143560514409678469862250207440675303576178809488957082804485944446225032956319749038833642485681946267959990181650810435723731755627693490958402541015772649403218387116342415453965710612578891122860080475980560084488514089712934013739781, - 30862742439593241585708940738147962226366718050501165321237842572436669411737554224118298772517486812375362296405238805912443683584456437953738131350045938787466841040220797401584428446174730486886913719857484102733725336155131475996004306581440515141136345274453183481082707684162136893963291137234740111704738897973555849945611157507740799100242851006495725457213328987753002399448999330977114104566617308036743409045315165685308303262653843118404666538923863063081603256452671995759383632696290823794779551389200638930288120410329395673124242908818519519330118489440718827371013019585524024323106350150372893461689, - 22979378405138893589556133897521754683725883868866200124855036635451629318130978502381364148180090802113404290988890710862982965215323041776178270890557477521858892737028622171038670089616608354902721183960978083779850093600290031995183687729693685221986115197995396115379213021683786733329612441286209467155931087319154615773299643384467163395079212511182788668809520330816917834693871112365384301753056859879036141250397887546537837356226101620007886380291232478721279115321079877121757818532329118011682430897866452653899829996834157870634757693124417404439069108796004756126487268680259509658734527559041787231993 - ], - "H1j": [ - 947268510305326446073634507724913447936734171636912400557401318775427643035322780043344044871778218536295489345747992085537349997385753459769909944243608187249295932620582767525243046024431872134558350124222211815956076009495579000118546531817489783543950708796804986346442485595844139040615169351977594594085460608932273701244091036215057114383266995365365226626217411088112095883376367775475107954293975266374705057036496941779873360807750450088301028537780564210964889218799820623451941121168857520561736570209171665676631521362739174866629364755585577716299287494251706261472512421959632149833106509542229972234, - 3880611998802971481733631912608098494196262778323132826239497201888814778206565779038508295122457059564658474446013387570155222804192995563846151508944721213706421845709980882611956739258515443677158361364276786837940404625680574358803765552923094221476122072037719326145018613827892918963555625064867923347247217043400958580189757825375746004023039968242295816205605839011845166061436412284630990719600784460170159747697580968014664501419463157750169639809058771175198577548493272625218114926414363501638734650889306046401503137104184980837461670247903219705017626260602184962369771097797399062562513353217770565531, - 10831225843690707396172531846155417775408096606230693395561759792282094678514600816663347869748948927505461627250570771469119140533266318664691242702922064589002187370016461932692821183944924214028723777910582605988927471997349297521445102656640882914313554019001846714781268540993241638422699989309757114468372538565383360692272346876551928106077801669528247179220120217249637229522616724754257258083101113512544707361337883525289735840725085893321825199206160881032044949147621462286088226618153585859120352649591156109044603116965314576319186213041333237791389005373191075396808136402252420638572954706343475908070, - 7379047495513012741768052948709028575585555485999633742902872635999567523931496397934138722681164927896829567152505037328183413349521525062101059035871423959216606865846805649228889409341121623645276995775466833580910793875325853108618331288089921648034916011339650914136927737993536151052450142994995957064434847339676185441357826456108823451579572271337009853306909251138234707237745952438799718674765118984490163866366131359672038740868456547662412411582409607895270049993194846640187000629665900662666631953358892682510778724505052220510687061629914270273761091793976303803161711621832014373503323366016634630406, - 11181628178709225486839172762330742659423724114653226835819397085381257304105257566937592702765853135360490266257083192830870077666275960663723976086310235934350572650480643691450656438652769853018111519504498965737440967647717818784480763727200258889702626069322469743838822112397983393755250519010298110374742466783922925487057158527359106287066137656141433380846258646250390469229071336860949790965072334352962521185854509550842351266605524163986806331802767702307634084162000820507840777885400805512071448246749124225768822589052733208381949931869152348048701648349767479285228581634453249080578720203097097514457 - ], - "H2j": [ - 369382535766024782757053511943484023707590301248858510505619543451105355366349475321600848828578055383112252081262740450957242693258711711573898608872557215737850380375149487180022863563616178163440683814662347260503803753150609907077552201623376131096249150783552367189222999632342102603491398593162398739317344334427947844029843540621897547082716967267285286086227255034044222917612280937408214149645699005643727644027239999997789724357422423935120674874708262799420509411969660535187315093553065000790565517535769427338692918882249946664488170641583406635227373502217028982923125561321182147198392699754510926843, - 15969079226966183502382475788401338523488393107499291032002044296474627394217596503568693748659928310923714663501210832583018731196547300812154979725769686288361401778491755680431944887852103221593745623856378860738388368922715577130878948380171217565406616753411777571011139446871620361320986832525400727639941640937364793530207582464684574638726091525574744197708378588020682070096454926012197394347212926657909811288708691651092564968341401161265195710381753419063864921935963903871011102644256286369641306466313805437318014970058871604639507243703932226939038829663830985880788590281053591951619664726739953671018, - 4991965837400033768069871541004261063135140339060316531025599789490182217840042887067892359235887756385798984623237629620830856274859128458536333773291056510054624668039972342087961925191332459597054733496082441434562377800869508105363637144128472861641912914050632826421706717769073047295100882343425757237060029497292934794235607113222710491355298594636899811931946648047811854321545995037508110462735244536402582555614331492107887985617810756386029525697146027973237905139754077084275404126435090136074550061845235250362605148173730041087342012184590101575852114035899339078096801167678750962125251280492197772961, - 23064781826724373162059309790268929175652024853806919970585039362565178134882146726172590403276064143405780341854075186376431326467367967581674319153076910116152907650926195389275015857432169732825486479963071595528043281158690951801576413614814760292960443710324174730418861380180819802157714395735784311928236401433597447641321165573011917942945482934111736905171027083754748263370419119297225245442731766002872688005764140266867116940180286239156118891196076208004108028110204585118322786319227036687507415330523815192275901354672284703528348057050369197376684323825935099945673108591425248965307506340817771591441, - 11624783050789373146135145081851167787144912685550655481254753886486876945039110175782945406523699017594888407389014880101840909734903251718897005090801524812985842948051908677768943122267838594824514706829210878634123695856103833890298708489700110861686115821849284312876390414092087922712380944749991516509300532655840012200292315982914838173353675847647411050340787544373391445319951232858137394531780600427092367231102522845204917484802409447548360146964783744378214393625590646132406343132441415352603518333034984771651345199420810327304168670235976704426708270671344968176457707557409261114405916868900751036145 - ], - "BigXj": [ - { - "Curve": "secp256k1", - "Coords": [ - 95225479287625109140551300097635441933915975782583911515343531112654602880814, - 113745830257261593369068705146261698861441809650110061237310141136031506190085 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 19909020077923456087962021369246692987785610885502332606764981730113023110067, - 60076350170225224442893367050676875983156697199114782416705437692213004111433 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15656029217860558075932288367874977299995954233140419375302609508233656030817, - 88293512119423239639079954683198441748713533855873639211876694257553830935691 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15825259379483050804368543653451724857970141958098760943464945060863314262898, - 46510254063758718632499733093297318465018983961512441577134679077369278627011 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 101163968142129288084264305494084191253074413300747651525777392366080313581620, - 19458713537429380315587854195885123660811710862685360770347430223563133437479 - ] - } - ], - "PaillierPKs": [ - { - "N": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185392600641669797286300834348740665304662829760721139573070204170902129262797162145018079946053388917283347495995703735479819366865064178966988962612678607190805087224162314010583832802161588455461100682306289046720947974174001828045869589748392310605782826097558345479795972515955139600004112610785604729710757 - }, - { - "N": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654571826800302294766234904003147622246551178854009373086133349568572584906962173774282191211244583738166117722131851467394725949126097483624199330170392292115956857647929895014719727669500452359666570376448590229755339126098108084513655351630004806845329610086536348250655270492083872210115099541350980087869489 - }, - { - "N": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114362935636941751781265771147161683942488081675636897258681038605775448214108367751993197065197897191643383564344845162403884453232776839031251175853763144050201714908798915379664014184087913029794762586324582687266708240565299184055542301695610690632283322864399949456272972805575542427101734659832898527078677 - }, - { - "N": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483556240372784852668293634144857453177818024665828049715609921864852313661181061967825839048394234894185931968992541576874445544364635775263264674967563604397356712492758200667296917972566268326712277912968541425534456091226445588857731271210711997226828598037017820056231841183710665446107873358077925757871906777 - }, - { - "N": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811976260936406546600112652090553738417255733994944221554428167638466246670287061019896463881779810197390238307556892485807795138448959345532929528137209046373349550262355661974463926686395148775662060236988349400478971416621513539908477667503550115870803074998306032371456267566517610267867391193312424397935929 - } - ], - "ECDSAPub": { - "Curve": "secp256k1", - "Coords": [ - 76266489189895419469020567248501927603989841769205411177925179985114092514949, - 17959638069442050620236663888410692330316152082152911789514411031446499229348 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_ecdsa_fixtures/keygen_data_2.json b/tss-lib/test/_ecdsa_fixtures/keygen_data_2.json deleted file mode 100644 index 6f204be..0000000 --- a/tss-lib/test/_ecdsa_fixtures/keygen_data_2.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "PaillierSK": { - "N": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114362935636941751781265771147161683942488081675636897258681038605775448214108367751993197065197897191643383564344845162403884453232776839031251175853763144050201714908798915379664014184087913029794762586324582687266708240565299184055542301695610690632283322864399949456272972805575542427101734659832898527078677, - "LambdaN": 12103073608098580584400374856897126548680087545429336465964067526650360049131651099929182109144804720491168139495191153435618652299451662194660790581533695399975295765513620484342847058134565751819724944588076422381034974241261940958374991023993511234133106351333419881203717746414286949421970189859043349557024310086219410477072748318487742739042777792072287595135146879759069811629897245323954026052320936771957200007617646395169281432170783039473463063929011840852856768971615621594157956524540453364109564204089902134439307707012750590999769391124192112406139571469549041961432228411468903953868707176804446220918, - "PhiN": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114048620172438820954145496636975485478085555584144575190270293759518139623259794490647908052104641873543914400015235292790338562864341566078946926127858023681705713537943231243188315913049080906728219128408179804268878615414025501181999538782248384224812279142939098083922864456822937807907737414353608892441836, - "P": 179347946090591232979004413467496114724106046225268285989836604667382648146344194469177416555876441903499128428642839375190430980577227664241391921790897322284182306801422645287586317496796904441090376224911593079648968209876923078326921963018765802933604070645734447691803536882758254809782260398835871487663, - "Q": 134967518412339594141270096718702349678420045267053782420908241589925942702229066876111596537378876195970035900967030238355459387858045288062857804114223046211819064054261491188111953542035218625453081691491289918180656941396759795215840950343540604537439650815116924658304811869846364384214985080453763149179 - }, - "NTildei": 21292308023632581181198289513256444712308177801737936647775817904740223548406904422170044682275257431431315028868812996459652895591102638516259762883465973519952131280804384814232387700680465986308431924126707276653911414520068641511680988816011871501850341616042836704357314055609697319128691732749390230733118584785117859207288385865822542643892497962395263780902218346962474333143560514409678469862250207440675303576178809488957082804485944446225032956319749038833642485681946267959990181650810435723731755627693490958402541015772649403218387116342415453965710612578891122860080475980560084488514089712934013739781, - "H1i": 10831225843690707396172531846155417775408096606230693395561759792282094678514600816663347869748948927505461627250570771469119140533266318664691242702922064589002187370016461932692821183944924214028723777910582605988927471997349297521445102656640882914313554019001846714781268540993241638422699989309757114468372538565383360692272346876551928106077801669528247179220120217249637229522616724754257258083101113512544707361337883525289735840725085893321825199206160881032044949147621462286088226618153585859120352649591156109044603116965314576319186213041333237791389005373191075396808136402252420638572954706343475908070, - "H2i": 4991965837400033768069871541004261063135140339060316531025599789490182217840042887067892359235887756385798984623237629620830856274859128458536333773291056510054624668039972342087961925191332459597054733496082441434562377800869508105363637144128472861641912914050632826421706717769073047295100882343425757237060029497292934794235607113222710491355298594636899811931946648047811854321545995037508110462735244536402582555614331492107887985617810756386029525697146027973237905139754077084275404126435090136074550061845235250362605148173730041087342012184590101575852114035899339078096801167678750962125251280492197772961, - "Alpha": 12467492105857811088598302265413624870073963876683904115549792420718244667761381421662233615179766169159301747248171001794324121204205514721429411527556422474730559769416341734269127480499195450639280845254825411204958752546880935506192531533720763834591807162931020700005834118949784903275082231197821697666438147146351494072123177022074937176886845914902073137041551203992966070392159928400957103356072574222408552466272801416682546062655619490834257111523501863902732635107221589080095740033399178826436203367881462984740273038927833790029236756977691739321073706751435418243818216736984796273413201551593241377745, - "Beta": 3092900433075562857730870820153450098596803035900780910921649947445993103830332321974327778125342409105586526032316509076255129195987441893584663089182631340709377726700826265326534446647512383669109999128575227820698317763796087420267115770338098171394186245601090936193819697220860084235631876618972161796183290283437286083205410206306343632327839214997496752240852724669373936278550652726231441900252091569385961205860343319878986257063348059860099745005755756686589281908205169093609472515987160341040392705054879831617033293887998222621876114828567467692369732362792302927316059137471591649253327901378732843111, - "P": 74729784971772398429529650577831893381748271883890759436992442977820668409070982447343050413507330989104807520612734716141235130908592245155908358608877871002264282164414418683122667727977065469038707348970011499327641988120347830292987877895400315533431826053732774970762953513006237872470250023861544322019, - "Q": 71230995886296547844286770147735054870849465379812954762983713904489759233350383164729814676282726841672841443277930887612560071405593846902336747858766127875795287445507639632096218873801296532878661675646715168843741383193429019420970355899846985062779107421621481264788608899327914283807067035047912995689, - "Xi": 9402118216258077893650330587582519725761707076837026476585485684614098285800, - "ShareID": 59857031556462284717113645237935722663924232558699039874171440941840562677325, - "Ks": [ - 59857031556462284717113645237935722663924232558699039874171440941840562677323, - 59857031556462284717113645237935722663924232558699039874171440941840562677324, - 59857031556462284717113645237935722663924232558699039874171440941840562677325, - 59857031556462284717113645237935722663924232558699039874171440941840562677326, - 59857031556462284717113645237935722663924232558699039874171440941840562677327 - ], - "NTildej": [ - 25107490776052945575790163886980744121852075793230702092031092910315419013111724585107741342302647097816029689069156500419649067226989207335403141846585589456214707140363806918024254341805807847344462552372749802373561411623464018306841140152736878126807643286464707464144491205717529334857128642937311664356950670200785184493082292988908234459722618881044613550904554507333793627844968327344517418351075665978629614435510466378211576459017353838583039397930178040557511540818370302033808216608330168909665648805527673068950251148153088673193641290377199021831923470431364077200419352774733381328839199321622201645277, - 25347321253130040165669198464747637594561084543160875890419030859255281770152898118930416834987900972848102624649324216864737441361174703716495863609322476087408028387965233238285802668149470294745292681572931725456001393301305606431470624857854001369500295623909754190673037775702216922020351830224578270444039819022050738946522292544390839130641700344286132805509002888252787493089063466842186838763536749516490621525613122365080892293964923531037888659136998882617232588657938236946761539565880695421135081565601958037809654399412376843665230604400657963765839300124472222517361299084266084873325229770349534163801, - 21292308023632581181198289513256444712308177801737936647775817904740223548406904422170044682275257431431315028868812996459652895591102638516259762883465973519952131280804384814232387700680465986308431924126707276653911414520068641511680988816011871501850341616042836704357314055609697319128691732749390230733118584785117859207288385865822542643892497962395263780902218346962474333143560514409678469862250207440675303576178809488957082804485944446225032956319749038833642485681946267959990181650810435723731755627693490958402541015772649403218387116342415453965710612578891122860080475980560084488514089712934013739781, - 30862742439593241585708940738147962226366718050501165321237842572436669411737554224118298772517486812375362296405238805912443683584456437953738131350045938787466841040220797401584428446174730486886913719857484102733725336155131475996004306581440515141136345274453183481082707684162136893963291137234740111704738897973555849945611157507740799100242851006495725457213328987753002399448999330977114104566617308036743409045315165685308303262653843118404666538923863063081603256452671995759383632696290823794779551389200638930288120410329395673124242908818519519330118489440718827371013019585524024323106350150372893461689, - 22979378405138893589556133897521754683725883868866200124855036635451629318130978502381364148180090802113404290988890710862982965215323041776178270890557477521858892737028622171038670089616608354902721183960978083779850093600290031995183687729693685221986115197995396115379213021683786733329612441286209467155931087319154615773299643384467163395079212511182788668809520330816917834693871112365384301753056859879036141250397887546537837356226101620007886380291232478721279115321079877121757818532329118011682430897866452653899829996834157870634757693124417404439069108796004756126487268680259509658734527559041787231993 - ], - "H1j": [ - 947268510305326446073634507724913447936734171636912400557401318775427643035322780043344044871778218536295489345747992085537349997385753459769909944243608187249295932620582767525243046024431872134558350124222211815956076009495579000118546531817489783543950708796804986346442485595844139040615169351977594594085460608932273701244091036215057114383266995365365226626217411088112095883376367775475107954293975266374705057036496941779873360807750450088301028537780564210964889218799820623451941121168857520561736570209171665676631521362739174866629364755585577716299287494251706261472512421959632149833106509542229972234, - 3880611998802971481733631912608098494196262778323132826239497201888814778206565779038508295122457059564658474446013387570155222804192995563846151508944721213706421845709980882611956739258515443677158361364276786837940404625680574358803765552923094221476122072037719326145018613827892918963555625064867923347247217043400958580189757825375746004023039968242295816205605839011845166061436412284630990719600784460170159747697580968014664501419463157750169639809058771175198577548493272625218114926414363501638734650889306046401503137104184980837461670247903219705017626260602184962369771097797399062562513353217770565531, - 10831225843690707396172531846155417775408096606230693395561759792282094678514600816663347869748948927505461627250570771469119140533266318664691242702922064589002187370016461932692821183944924214028723777910582605988927471997349297521445102656640882914313554019001846714781268540993241638422699989309757114468372538565383360692272346876551928106077801669528247179220120217249637229522616724754257258083101113512544707361337883525289735840725085893321825199206160881032044949147621462286088226618153585859120352649591156109044603116965314576319186213041333237791389005373191075396808136402252420638572954706343475908070, - 7379047495513012741768052948709028575585555485999633742902872635999567523931496397934138722681164927896829567152505037328183413349521525062101059035871423959216606865846805649228889409341121623645276995775466833580910793875325853108618331288089921648034916011339650914136927737993536151052450142994995957064434847339676185441357826456108823451579572271337009853306909251138234707237745952438799718674765118984490163866366131359672038740868456547662412411582409607895270049993194846640187000629665900662666631953358892682510778724505052220510687061629914270273761091793976303803161711621832014373503323366016634630406, - 11181628178709225486839172762330742659423724114653226835819397085381257304105257566937592702765853135360490266257083192830870077666275960663723976086310235934350572650480643691450656438652769853018111519504498965737440967647717818784480763727200258889702626069322469743838822112397983393755250519010298110374742466783922925487057158527359106287066137656141433380846258646250390469229071336860949790965072334352962521185854509550842351266605524163986806331802767702307634084162000820507840777885400805512071448246749124225768822589052733208381949931869152348048701648349767479285228581634453249080578720203097097514457 - ], - "H2j": [ - 369382535766024782757053511943484023707590301248858510505619543451105355366349475321600848828578055383112252081262740450957242693258711711573898608872557215737850380375149487180022863563616178163440683814662347260503803753150609907077552201623376131096249150783552367189222999632342102603491398593162398739317344334427947844029843540621897547082716967267285286086227255034044222917612280937408214149645699005643727644027239999997789724357422423935120674874708262799420509411969660535187315093553065000790565517535769427338692918882249946664488170641583406635227373502217028982923125561321182147198392699754510926843, - 15969079226966183502382475788401338523488393107499291032002044296474627394217596503568693748659928310923714663501210832583018731196547300812154979725769686288361401778491755680431944887852103221593745623856378860738388368922715577130878948380171217565406616753411777571011139446871620361320986832525400727639941640937364793530207582464684574638726091525574744197708378588020682070096454926012197394347212926657909811288708691651092564968341401161265195710381753419063864921935963903871011102644256286369641306466313805437318014970058871604639507243703932226939038829663830985880788590281053591951619664726739953671018, - 4991965837400033768069871541004261063135140339060316531025599789490182217840042887067892359235887756385798984623237629620830856274859128458536333773291056510054624668039972342087961925191332459597054733496082441434562377800869508105363637144128472861641912914050632826421706717769073047295100882343425757237060029497292934794235607113222710491355298594636899811931946648047811854321545995037508110462735244536402582555614331492107887985617810756386029525697146027973237905139754077084275404126435090136074550061845235250362605148173730041087342012184590101575852114035899339078096801167678750962125251280492197772961, - 23064781826724373162059309790268929175652024853806919970585039362565178134882146726172590403276064143405780341854075186376431326467367967581674319153076910116152907650926195389275015857432169732825486479963071595528043281158690951801576413614814760292960443710324174730418861380180819802157714395735784311928236401433597447641321165573011917942945482934111736905171027083754748263370419119297225245442731766002872688005764140266867116940180286239156118891196076208004108028110204585118322786319227036687507415330523815192275901354672284703528348057050369197376684323825935099945673108591425248965307506340817771591441, - 11624783050789373146135145081851167787144912685550655481254753886486876945039110175782945406523699017594888407389014880101840909734903251718897005090801524812985842948051908677768943122267838594824514706829210878634123695856103833890298708489700110861686115821849284312876390414092087922712380944749991516509300532655840012200292315982914838173353675847647411050340787544373391445319951232858137394531780600427092367231102522845204917484802409447548360146964783744378214393625590646132406343132441415352603518333034984771651345199420810327304168670235976704426708270671344968176457707557409261114405916868900751036145 - ], - "BigXj": [ - { - "Curve": "secp256k1", - "Coords": [ - 95225479287625109140551300097635441933915975782583911515343531112654602880814, - 113745830257261593369068705146261698861441809650110061237310141136031506190085 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 19909020077923456087962021369246692987785610885502332606764981730113023110067, - 60076350170225224442893367050676875983156697199114782416705437692213004111433 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15656029217860558075932288367874977299995954233140419375302609508233656030817, - 88293512119423239639079954683198441748713533855873639211876694257553830935691 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15825259379483050804368543653451724857970141958098760943464945060863314262898, - 46510254063758718632499733093297318465018983961512441577134679077369278627011 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 101163968142129288084264305494084191253074413300747651525777392366080313581620, - 19458713537429380315587854195885123660811710862685360770347430223563133437479 - ] - } - ], - "PaillierPKs": [ - { - "N": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185392600641669797286300834348740665304662829760721139573070204170902129262797162145018079946053388917283347495995703735479819366865064178966988962612678607190805087224162314010583832802161588455461100682306289046720947974174001828045869589748392310605782826097558345479795972515955139600004112610785604729710757 - }, - { - "N": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654571826800302294766234904003147622246551178854009373086133349568572584906962173774282191211244583738166117722131851467394725949126097483624199330170392292115956857647929895014719727669500452359666570376448590229755339126098108084513655351630004806845329610086536348250655270492083872210115099541350980087869489 - }, - { - "N": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114362935636941751781265771147161683942488081675636897258681038605775448214108367751993197065197897191643383564344845162403884453232776839031251175853763144050201714908798915379664014184087913029794762586324582687266708240565299184055542301695610690632283322864399949456272972805575542427101734659832898527078677 - }, - { - "N": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483556240372784852668293634144857453177818024665828049715609921864852313661181061967825839048394234894185931968992541576874445544364635775263264674967563604397356712492758200667296917972566268326712277912968541425534456091226445588857731271210711997226828598037017820056231841183710665446107873358077925757871906777 - }, - { - "N": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811976260936406546600112652090553738417255733994944221554428167638466246670287061019896463881779810197390238307556892485807795138448959345532929528137209046373349550262355661974463926686395148775662060236988349400478971416621513539908477667503550115870803074998306032371456267566517610267867391193312424397935929 - } - ], - "ECDSAPub": { - "Curve": "secp256k1", - "Coords": [ - 76266489189895419469020567248501927603989841769205411177925179985114092514949, - 17959638069442050620236663888410692330316152082152911789514411031446499229348 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_ecdsa_fixtures/keygen_data_3.json b/tss-lib/test/_ecdsa_fixtures/keygen_data_3.json deleted file mode 100644 index 377f5f7..0000000 --- a/tss-lib/test/_ecdsa_fixtures/keygen_data_3.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "PaillierSK": { - "N": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483556240372784852668293634144857453177818024665828049715609921864852313661181061967825839048394234894185931968992541576874445544364635775263264674967563604397356712492758200667296917972566268326712277912968541425534456091226445588857731271210711997226828598037017820056231841183710665446107873358077925757871906777, - "LambdaN": 13711066678925685158481892661407594802363287874057028858992418705885878035136241463479449379288107635953645781075967754388620024185459543845554681779377313526469591520019750655174412403608597211731033898134489626486195114796256401901052870760416840510868776246134787245182477749727744251809525469906467241777954213500922962598207900244610615470932048383158628700567162631631189503587620334276701648788930166782916153827195929574382625322547232728203845276358810162861271567739888395670907555222537982867559801824374155710793133779866475562224398329799259589595882004342841775151121290158152012860933070519454708809498, - "PhiN": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483555908427001845925196415800489221230941864096766317257401134325263262379007175240668553403297577860333565832307654391859148765250645094465456407690552717620325722543135479776791341815110445075965735119603648748311421586267559732951124448796659598519179191764008685683550302242580316304025721866141038909417618996, - "P": 177147297802525579102993050062131223090295228216279191453242872804814556506749685154258555822845767694821633091957303084556832484826430719319109868163685560366598818468952708376164311637165401295038149681028640001543182713340547770949859961750808928993661379228653713884473377336021514701747429842270320596239, - "Q": 154798485204217518115351318169815653070273833516179017334296716246467617379977472131386540834188084671315051795227712212222281505854367088948167142723091470623350804251937797199993144186085345247755215211648583032961776172515358835872554090647898720412611629905718967654467753013120567449744507044578133691543 - }, - "NTildei": 30862742439593241585708940738147962226366718050501165321237842572436669411737554224118298772517486812375362296405238805912443683584456437953738131350045938787466841040220797401584428446174730486886913719857484102733725336155131475996004306581440515141136345274453183481082707684162136893963291137234740111704738897973555849945611157507740799100242851006495725457213328987753002399448999330977114104566617308036743409045315165685308303262653843118404666538923863063081603256452671995759383632696290823794779551389200638930288120410329395673124242908818519519330118489440718827371013019585524024323106350150372893461689, - "H1i": 7379047495513012741768052948709028575585555485999633742902872635999567523931496397934138722681164927896829567152505037328183413349521525062101059035871423959216606865846805649228889409341121623645276995775466833580910793875325853108618331288089921648034916011339650914136927737993536151052450142994995957064434847339676185441357826456108823451579572271337009853306909251138234707237745952438799718674765118984490163866366131359672038740868456547662412411582409607895270049993194846640187000629665900662666631953358892682510778724505052220510687061629914270273761091793976303803161711621832014373503323366016634630406, - "H2i": 23064781826724373162059309790268929175652024853806919970585039362565178134882146726172590403276064143405780341854075186376431326467367967581674319153076910116152907650926195389275015857432169732825486479963071595528043281158690951801576413614814760292960443710324174730418861380180819802157714395735784311928236401433597447641321165573011917942945482934111736905171027083754748263370419119297225245442731766002872688005764140266867116940180286239156118891196076208004108028110204585118322786319227036687507415330523815192275901354672284703528348057050369197376684323825935099945673108591425248965307506340817771591441, - "Alpha": 4648622922365995691950852472307693991496748717650755886041472758966649772223577185560503709377403263490257440740160039880829025875460382743719657106043215046874887472104366457266719570185588106832548763709423754442528268880550658756292061197437488907821505351342887275050423812794709440946117410292944992197499521419994551410803216027766619098594614692274903134932000727788522050861446364496906190349211518548008043980245101419488037879799945724570352667459813306016191262247735401344569214934207946586389966378909900863650262061552284378821161631397536341267121590001946593992670005380822124185382452984619192964296, - "Beta": 7283035794852630027597719507311988400352157227741064867320944375271311410043321457567543258900687773840402210832336699099355652336427138303463630478259640028368969060077262761882674943258400609728464897259824878619654205445207266962415152720307340810440440488319215406143967306140587488336460685951455315996674081010575049283159077953679770530039740316932302759499007229971328506788005448873223090633785198376902652454598099861304289786086831409011204427476269302086833451326645185421061429645318495124264857467498648034188324619279322211616547377743903673008882675216867616790252156678523580698939063094811432804106, - "P": 88946853524429644157279692699940537205256244584836191357676563352646399437711907359597600783173787788473495644611336583533678480415103123545022822524172251070286490589683779917058542223015781748214551278028480200408190616872417308222241413563336739390358317830977287500459962096931426244013093349893192168943, - "Q": 86744896577810517384645824130564891628128716346237962081502021347048770344272448219940628925379372197310560098081816109684647116457382634604974690735098205059906140134063148657379351812283596597272202732430603458302975974954397686666228707698307455286780720136391242400469746586788331488821897115156771081523, - "Xi": 40862812087778895933409199889429465759884835742974119277932406627299270252737, - "ShareID": 59857031556462284717113645237935722663924232558699039874171440941840562677326, - "Ks": [ - 59857031556462284717113645237935722663924232558699039874171440941840562677323, - 59857031556462284717113645237935722663924232558699039874171440941840562677324, - 59857031556462284717113645237935722663924232558699039874171440941840562677325, - 59857031556462284717113645237935722663924232558699039874171440941840562677326, - 59857031556462284717113645237935722663924232558699039874171440941840562677327 - ], - "NTildej": [ - 25107490776052945575790163886980744121852075793230702092031092910315419013111724585107741342302647097816029689069156500419649067226989207335403141846585589456214707140363806918024254341805807847344462552372749802373561411623464018306841140152736878126807643286464707464144491205717529334857128642937311664356950670200785184493082292988908234459722618881044613550904554507333793627844968327344517418351075665978629614435510466378211576459017353838583039397930178040557511540818370302033808216608330168909665648805527673068950251148153088673193641290377199021831923470431364077200419352774733381328839199321622201645277, - 25347321253130040165669198464747637594561084543160875890419030859255281770152898118930416834987900972848102624649324216864737441361174703716495863609322476087408028387965233238285802668149470294745292681572931725456001393301305606431470624857854001369500295623909754190673037775702216922020351830224578270444039819022050738946522292544390839130641700344286132805509002888252787493089063466842186838763536749516490621525613122365080892293964923531037888659136998882617232588657938236946761539565880695421135081565601958037809654399412376843665230604400657963765839300124472222517361299084266084873325229770349534163801, - 21292308023632581181198289513256444712308177801737936647775817904740223548406904422170044682275257431431315028868812996459652895591102638516259762883465973519952131280804384814232387700680465986308431924126707276653911414520068641511680988816011871501850341616042836704357314055609697319128691732749390230733118584785117859207288385865822542643892497962395263780902218346962474333143560514409678469862250207440675303576178809488957082804485944446225032956319749038833642485681946267959990181650810435723731755627693490958402541015772649403218387116342415453965710612578891122860080475980560084488514089712934013739781, - 30862742439593241585708940738147962226366718050501165321237842572436669411737554224118298772517486812375362296405238805912443683584456437953738131350045938787466841040220797401584428446174730486886913719857484102733725336155131475996004306581440515141136345274453183481082707684162136893963291137234740111704738897973555849945611157507740799100242851006495725457213328987753002399448999330977114104566617308036743409045315165685308303262653843118404666538923863063081603256452671995759383632696290823794779551389200638930288120410329395673124242908818519519330118489440718827371013019585524024323106350150372893461689, - 22979378405138893589556133897521754683725883868866200124855036635451629318130978502381364148180090802113404290988890710862982965215323041776178270890557477521858892737028622171038670089616608354902721183960978083779850093600290031995183687729693685221986115197995396115379213021683786733329612441286209467155931087319154615773299643384467163395079212511182788668809520330816917834693871112365384301753056859879036141250397887546537837356226101620007886380291232478721279115321079877121757818532329118011682430897866452653899829996834157870634757693124417404439069108796004756126487268680259509658734527559041787231993 - ], - "H1j": [ - 947268510305326446073634507724913447936734171636912400557401318775427643035322780043344044871778218536295489345747992085537349997385753459769909944243608187249295932620582767525243046024431872134558350124222211815956076009495579000118546531817489783543950708796804986346442485595844139040615169351977594594085460608932273701244091036215057114383266995365365226626217411088112095883376367775475107954293975266374705057036496941779873360807750450088301028537780564210964889218799820623451941121168857520561736570209171665676631521362739174866629364755585577716299287494251706261472512421959632149833106509542229972234, - 3880611998802971481733631912608098494196262778323132826239497201888814778206565779038508295122457059564658474446013387570155222804192995563846151508944721213706421845709980882611956739258515443677158361364276786837940404625680574358803765552923094221476122072037719326145018613827892918963555625064867923347247217043400958580189757825375746004023039968242295816205605839011845166061436412284630990719600784460170159747697580968014664501419463157750169639809058771175198577548493272625218114926414363501638734650889306046401503137104184980837461670247903219705017626260602184962369771097797399062562513353217770565531, - 10831225843690707396172531846155417775408096606230693395561759792282094678514600816663347869748948927505461627250570771469119140533266318664691242702922064589002187370016461932692821183944924214028723777910582605988927471997349297521445102656640882914313554019001846714781268540993241638422699989309757114468372538565383360692272346876551928106077801669528247179220120217249637229522616724754257258083101113512544707361337883525289735840725085893321825199206160881032044949147621462286088226618153585859120352649591156109044603116965314576319186213041333237791389005373191075396808136402252420638572954706343475908070, - 7379047495513012741768052948709028575585555485999633742902872635999567523931496397934138722681164927896829567152505037328183413349521525062101059035871423959216606865846805649228889409341121623645276995775466833580910793875325853108618331288089921648034916011339650914136927737993536151052450142994995957064434847339676185441357826456108823451579572271337009853306909251138234707237745952438799718674765118984490163866366131359672038740868456547662412411582409607895270049993194846640187000629665900662666631953358892682510778724505052220510687061629914270273761091793976303803161711621832014373503323366016634630406, - 11181628178709225486839172762330742659423724114653226835819397085381257304105257566937592702765853135360490266257083192830870077666275960663723976086310235934350572650480643691450656438652769853018111519504498965737440967647717818784480763727200258889702626069322469743838822112397983393755250519010298110374742466783922925487057158527359106287066137656141433380846258646250390469229071336860949790965072334352962521185854509550842351266605524163986806331802767702307634084162000820507840777885400805512071448246749124225768822589052733208381949931869152348048701648349767479285228581634453249080578720203097097514457 - ], - "H2j": [ - 369382535766024782757053511943484023707590301248858510505619543451105355366349475321600848828578055383112252081262740450957242693258711711573898608872557215737850380375149487180022863563616178163440683814662347260503803753150609907077552201623376131096249150783552367189222999632342102603491398593162398739317344334427947844029843540621897547082716967267285286086227255034044222917612280937408214149645699005643727644027239999997789724357422423935120674874708262799420509411969660535187315093553065000790565517535769427338692918882249946664488170641583406635227373502217028982923125561321182147198392699754510926843, - 15969079226966183502382475788401338523488393107499291032002044296474627394217596503568693748659928310923714663501210832583018731196547300812154979725769686288361401778491755680431944887852103221593745623856378860738388368922715577130878948380171217565406616753411777571011139446871620361320986832525400727639941640937364793530207582464684574638726091525574744197708378588020682070096454926012197394347212926657909811288708691651092564968341401161265195710381753419063864921935963903871011102644256286369641306466313805437318014970058871604639507243703932226939038829663830985880788590281053591951619664726739953671018, - 4991965837400033768069871541004261063135140339060316531025599789490182217840042887067892359235887756385798984623237629620830856274859128458536333773291056510054624668039972342087961925191332459597054733496082441434562377800869508105363637144128472861641912914050632826421706717769073047295100882343425757237060029497292934794235607113222710491355298594636899811931946648047811854321545995037508110462735244536402582555614331492107887985617810756386029525697146027973237905139754077084275404126435090136074550061845235250362605148173730041087342012184590101575852114035899339078096801167678750962125251280492197772961, - 23064781826724373162059309790268929175652024853806919970585039362565178134882146726172590403276064143405780341854075186376431326467367967581674319153076910116152907650926195389275015857432169732825486479963071595528043281158690951801576413614814760292960443710324174730418861380180819802157714395735784311928236401433597447641321165573011917942945482934111736905171027083754748263370419119297225245442731766002872688005764140266867116940180286239156118891196076208004108028110204585118322786319227036687507415330523815192275901354672284703528348057050369197376684323825935099945673108591425248965307506340817771591441, - 11624783050789373146135145081851167787144912685550655481254753886486876945039110175782945406523699017594888407389014880101840909734903251718897005090801524812985842948051908677768943122267838594824514706829210878634123695856103833890298708489700110861686115821849284312876390414092087922712380944749991516509300532655840012200292315982914838173353675847647411050340787544373391445319951232858137394531780600427092367231102522845204917484802409447548360146964783744378214393625590646132406343132441415352603518333034984771651345199420810327304168670235976704426708270671344968176457707557409261114405916868900751036145 - ], - "BigXj": [ - { - "Curve": "secp256k1", - "Coords": [ - 95225479287625109140551300097635441933915975782583911515343531112654602880814, - 113745830257261593369068705146261698861441809650110061237310141136031506190085 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 19909020077923456087962021369246692987785610885502332606764981730113023110067, - 60076350170225224442893367050676875983156697199114782416705437692213004111433 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15656029217860558075932288367874977299995954233140419375302609508233656030817, - 88293512119423239639079954683198441748713533855873639211876694257553830935691 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15825259379483050804368543653451724857970141958098760943464945060863314262898, - 46510254063758718632499733093297318465018983961512441577134679077369278627011 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 101163968142129288084264305494084191253074413300747651525777392366080313581620, - 19458713537429380315587854195885123660811710862685360770347430223563133437479 - ] - } - ], - "PaillierPKs": [ - { - "N": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185392600641669797286300834348740665304662829760721139573070204170902129262797162145018079946053388917283347495995703735479819366865064178966988962612678607190805087224162314010583832802161588455461100682306289046720947974174001828045869589748392310605782826097558345479795972515955139600004112610785604729710757 - }, - { - "N": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654571826800302294766234904003147622246551178854009373086133349568572584906962173774282191211244583738166117722131851467394725949126097483624199330170392292115956857647929895014719727669500452359666570376448590229755339126098108084513655351630004806845329610086536348250655270492083872210115099541350980087869489 - }, - { - "N": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114362935636941751781265771147161683942488081675636897258681038605775448214108367751993197065197897191643383564344845162403884453232776839031251175853763144050201714908798915379664014184087913029794762586324582687266708240565299184055542301695610690632283322864399949456272972805575542427101734659832898527078677 - }, - { - "N": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483556240372784852668293634144857453177818024665828049715609921864852313661181061967825839048394234894185931968992541576874445544364635775263264674967563604397356712492758200667296917972566268326712277912968541425534456091226445588857731271210711997226828598037017820056231841183710665446107873358077925757871906777 - }, - { - "N": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811976260936406546600112652090553738417255733994944221554428167638466246670287061019896463881779810197390238307556892485807795138448959345532929528137209046373349550262355661974463926686395148775662060236988349400478971416621513539908477667503550115870803074998306032371456267566517610267867391193312424397935929 - } - ], - "ECDSAPub": { - "Curve": "secp256k1", - "Coords": [ - 76266489189895419469020567248501927603989841769205411177925179985114092514949, - 17959638069442050620236663888410692330316152082152911789514411031446499229348 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_ecdsa_fixtures/keygen_data_4.json b/tss-lib/test/_ecdsa_fixtures/keygen_data_4.json deleted file mode 100644 index aad49b6..0000000 --- a/tss-lib/test/_ecdsa_fixtures/keygen_data_4.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "PaillierSK": { - "N": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811976260936406546600112652090553738417255733994944221554428167638466246670287061019896463881779810197390238307556892485807795138448959345532929528137209046373349550262355661974463926686395148775662060236988349400478971416621513539908477667503550115870803074998306032371456267566517610267867391193312424397935929, - "LambdaN": 10752980237317225656582239726923623349474534408084271725378943701390819222235042731507354681313826277457952659702353548779468025645187230438464369326041285139296544712214712430306538304447489961881145178171586824253674246146184031401084455876412426564859784031094087226834065533353146224100266852661983071405841009806066377556363073246749711470669165019696231902877884780913836332354683627070599850615352747373967268175605638682997172469714109771448131783193870242315301315250229103155846998372468463602427490952881430803570477256250706776089292559939188573801844886050618595015608293574001360336821185472476925563642, - "PhiN": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811682019612132755112726146493499422941338330039392463805755769561827672664709367254141199701230705494747934536351211277365994344939428219542896263566387740484630602630500458206311693996744936927204854981905762861607140954512501413552178585119878377147603689772101237190031216587148002720673642370944953851127284, - "P": 135350838307960257887337158821773449178953711379177117359015513540391289755315134832276760618216543327963109761712067613269505433440747687880030354506739527233631716724697521173335989032180031336807107200570956811703022411478868437314661062648778515879021174080716096058754325767045869446778292179625314996503, - "Q": 158890485965831229499168438232542026738450244172580631313382563098182715822378630922987419930888159314340661443969140828531288076090378302153234216314566361485315915130506246978896700618031817120398147882015582060127439697533257918984421321022960207320364052124079085366296653602561677746970530187845231812143 - }, - "NTildei": 22979378405138893589556133897521754683725883868866200124855036635451629318130978502381364148180090802113404290988890710862982965215323041776178270890557477521858892737028622171038670089616608354902721183960978083779850093600290031995183687729693685221986115197995396115379213021683786733329612441286209467155931087319154615773299643384467163395079212511182788668809520330816917834693871112365384301753056859879036141250397887546537837356226101620007886380291232478721279115321079877121757818532329118011682430897866452653899829996834157870634757693124417404439069108796004756126487268680259509658734527559041787231993, - "H1i": 11181628178709225486839172762330742659423724114653226835819397085381257304105257566937592702765853135360490266257083192830870077666275960663723976086310235934350572650480643691450656438652769853018111519504498965737440967647717818784480763727200258889702626069322469743838822112397983393755250519010298110374742466783922925487057158527359106287066137656141433380846258646250390469229071336860949790965072334352962521185854509550842351266605524163986806331802767702307634084162000820507840777885400805512071448246749124225768822589052733208381949931869152348048701648349767479285228581634453249080578720203097097514457, - "H2i": 11624783050789373146135145081851167787144912685550655481254753886486876945039110175782945406523699017594888407389014880101840909734903251718897005090801524812985842948051908677768943122267838594824514706829210878634123695856103833890298708489700110861686115821849284312876390414092087922712380944749991516509300532655840012200292315982914838173353675847647411050340787544373391445319951232858137394531780600427092367231102522845204917484802409447548360146964783744378214393625590646132406343132441415352603518333034984771651345199420810327304168670235976704426708270671344968176457707557409261114405916868900751036145, - "Alpha": 16240540962261166004211970670812971351480203151037237582769828801814689525653208090910663340159713344814790831486977215754908287497313853309804006226093506601752934119941709910453812455423784202324364228489440854102131033285288331999985864329846570322740304539785450985749381916050412115349790862491262399788251446971690344814332203163069600100340564179945886153017458386787068823782780403673848142124799383400779585915079517483545276218709468874820194872973213460799414555908836840291102289352318644049681699355227143818533468279900814783675013067347821048414318605018045347020498434873018402652391925998151906681941, - "Beta": 1723486697459218047345604944772577398595639174446372449733469017724037824646478073064036284409738447924923034349448915684865600027347429475331153769234544742762414746360506319339234569983871611652069442411059465102055257649507600765942646810180088097484550429298851479894694459800203980598253964419400048854156356200276777683732373765075415376989469613023233067835757787743964029401819512542611693471394988936548362080624781089282229422881682692850815018172571782677656491615083411197752197777949430384797246039266880644209517450862071108122536325302378370382044491103427488921489419539584033950495975894166924830598, - "P": 69497403900123055294512695371047987091100944784074526174548213609978119582884267995733221177643872461269822394244331609122728065030878548482603080986500743257678469453891586349369737631257188634428830962126742079718576995795162060648624476811816692784132596469903818449790670542178059258561916780466601681803, - "Q": 82662722330474726002641887846339461045747814112775706988763403904216639639472599582628541320325221413967353610050290850627993655720017622068669883265061738024090693419531380792968916424065879550143820413896195191562138594863014885149637306127518260357308690216048155754633897361170932639172413877671942265399, - "Xi": 55538075200338111200259293729261221540075119582900623624784541200756428158033, - "ShareID": 59857031556462284717113645237935722663924232558699039874171440941840562677327, - "Ks": [ - 59857031556462284717113645237935722663924232558699039874171440941840562677323, - 59857031556462284717113645237935722663924232558699039874171440941840562677324, - 59857031556462284717113645237935722663924232558699039874171440941840562677325, - 59857031556462284717113645237935722663924232558699039874171440941840562677326, - 59857031556462284717113645237935722663924232558699039874171440941840562677327 - ], - "NTildej": [ - 25107490776052945575790163886980744121852075793230702092031092910315419013111724585107741342302647097816029689069156500419649067226989207335403141846585589456214707140363806918024254341805807847344462552372749802373561411623464018306841140152736878126807643286464707464144491205717529334857128642937311664356950670200785184493082292988908234459722618881044613550904554507333793627844968327344517418351075665978629614435510466378211576459017353838583039397930178040557511540818370302033808216608330168909665648805527673068950251148153088673193641290377199021831923470431364077200419352774733381328839199321622201645277, - 25347321253130040165669198464747637594561084543160875890419030859255281770152898118930416834987900972848102624649324216864737441361174703716495863609322476087408028387965233238285802668149470294745292681572931725456001393301305606431470624857854001369500295623909754190673037775702216922020351830224578270444039819022050738946522292544390839130641700344286132805509002888252787493089063466842186838763536749516490621525613122365080892293964923531037888659136998882617232588657938236946761539565880695421135081565601958037809654399412376843665230604400657963765839300124472222517361299084266084873325229770349534163801, - 21292308023632581181198289513256444712308177801737936647775817904740223548406904422170044682275257431431315028868812996459652895591102638516259762883465973519952131280804384814232387700680465986308431924126707276653911414520068641511680988816011871501850341616042836704357314055609697319128691732749390230733118584785117859207288385865822542643892497962395263780902218346962474333143560514409678469862250207440675303576178809488957082804485944446225032956319749038833642485681946267959990181650810435723731755627693490958402541015772649403218387116342415453965710612578891122860080475980560084488514089712934013739781, - 30862742439593241585708940738147962226366718050501165321237842572436669411737554224118298772517486812375362296405238805912443683584456437953738131350045938787466841040220797401584428446174730486886913719857484102733725336155131475996004306581440515141136345274453183481082707684162136893963291137234740111704738897973555849945611157507740799100242851006495725457213328987753002399448999330977114104566617308036743409045315165685308303262653843118404666538923863063081603256452671995759383632696290823794779551389200638930288120410329395673124242908818519519330118489440718827371013019585524024323106350150372893461689, - 22979378405138893589556133897521754683725883868866200124855036635451629318130978502381364148180090802113404290988890710862982965215323041776178270890557477521858892737028622171038670089616608354902721183960978083779850093600290031995183687729693685221986115197995396115379213021683786733329612441286209467155931087319154615773299643384467163395079212511182788668809520330816917834693871112365384301753056859879036141250397887546537837356226101620007886380291232478721279115321079877121757818532329118011682430897866452653899829996834157870634757693124417404439069108796004756126487268680259509658734527559041787231993 - ], - "H1j": [ - 947268510305326446073634507724913447936734171636912400557401318775427643035322780043344044871778218536295489345747992085537349997385753459769909944243608187249295932620582767525243046024431872134558350124222211815956076009495579000118546531817489783543950708796804986346442485595844139040615169351977594594085460608932273701244091036215057114383266995365365226626217411088112095883376367775475107954293975266374705057036496941779873360807750450088301028537780564210964889218799820623451941121168857520561736570209171665676631521362739174866629364755585577716299287494251706261472512421959632149833106509542229972234, - 3880611998802971481733631912608098494196262778323132826239497201888814778206565779038508295122457059564658474446013387570155222804192995563846151508944721213706421845709980882611956739258515443677158361364276786837940404625680574358803765552923094221476122072037719326145018613827892918963555625064867923347247217043400958580189757825375746004023039968242295816205605839011845166061436412284630990719600784460170159747697580968014664501419463157750169639809058771175198577548493272625218114926414363501638734650889306046401503137104184980837461670247903219705017626260602184962369771097797399062562513353217770565531, - 10831225843690707396172531846155417775408096606230693395561759792282094678514600816663347869748948927505461627250570771469119140533266318664691242702922064589002187370016461932692821183944924214028723777910582605988927471997349297521445102656640882914313554019001846714781268540993241638422699989309757114468372538565383360692272346876551928106077801669528247179220120217249637229522616724754257258083101113512544707361337883525289735840725085893321825199206160881032044949147621462286088226618153585859120352649591156109044603116965314576319186213041333237791389005373191075396808136402252420638572954706343475908070, - 7379047495513012741768052948709028575585555485999633742902872635999567523931496397934138722681164927896829567152505037328183413349521525062101059035871423959216606865846805649228889409341121623645276995775466833580910793875325853108618331288089921648034916011339650914136927737993536151052450142994995957064434847339676185441357826456108823451579572271337009853306909251138234707237745952438799718674765118984490163866366131359672038740868456547662412411582409607895270049993194846640187000629665900662666631953358892682510778724505052220510687061629914270273761091793976303803161711621832014373503323366016634630406, - 11181628178709225486839172762330742659423724114653226835819397085381257304105257566937592702765853135360490266257083192830870077666275960663723976086310235934350572650480643691450656438652769853018111519504498965737440967647717818784480763727200258889702626069322469743838822112397983393755250519010298110374742466783922925487057158527359106287066137656141433380846258646250390469229071336860949790965072334352962521185854509550842351266605524163986806331802767702307634084162000820507840777885400805512071448246749124225768822589052733208381949931869152348048701648349767479285228581634453249080578720203097097514457 - ], - "H2j": [ - 369382535766024782757053511943484023707590301248858510505619543451105355366349475321600848828578055383112252081262740450957242693258711711573898608872557215737850380375149487180022863563616178163440683814662347260503803753150609907077552201623376131096249150783552367189222999632342102603491398593162398739317344334427947844029843540621897547082716967267285286086227255034044222917612280937408214149645699005643727644027239999997789724357422423935120674874708262799420509411969660535187315093553065000790565517535769427338692918882249946664488170641583406635227373502217028982923125561321182147198392699754510926843, - 15969079226966183502382475788401338523488393107499291032002044296474627394217596503568693748659928310923714663501210832583018731196547300812154979725769686288361401778491755680431944887852103221593745623856378860738388368922715577130878948380171217565406616753411777571011139446871620361320986832525400727639941640937364793530207582464684574638726091525574744197708378588020682070096454926012197394347212926657909811288708691651092564968341401161265195710381753419063864921935963903871011102644256286369641306466313805437318014970058871604639507243703932226939038829663830985880788590281053591951619664726739953671018, - 4991965837400033768069871541004261063135140339060316531025599789490182217840042887067892359235887756385798984623237629620830856274859128458536333773291056510054624668039972342087961925191332459597054733496082441434562377800869508105363637144128472861641912914050632826421706717769073047295100882343425757237060029497292934794235607113222710491355298594636899811931946648047811854321545995037508110462735244536402582555614331492107887985617810756386029525697146027973237905139754077084275404126435090136074550061845235250362605148173730041087342012184590101575852114035899339078096801167678750962125251280492197772961, - 23064781826724373162059309790268929175652024853806919970585039362565178134882146726172590403276064143405780341854075186376431326467367967581674319153076910116152907650926195389275015857432169732825486479963071595528043281158690951801576413614814760292960443710324174730418861380180819802157714395735784311928236401433597447641321165573011917942945482934111736905171027083754748263370419119297225245442731766002872688005764140266867116940180286239156118891196076208004108028110204585118322786319227036687507415330523815192275901354672284703528348057050369197376684323825935099945673108591425248965307506340817771591441, - 11624783050789373146135145081851167787144912685550655481254753886486876945039110175782945406523699017594888407389014880101840909734903251718897005090801524812985842948051908677768943122267838594824514706829210878634123695856103833890298708489700110861686115821849284312876390414092087922712380944749991516509300532655840012200292315982914838173353675847647411050340787544373391445319951232858137394531780600427092367231102522845204917484802409447548360146964783744378214393625590646132406343132441415352603518333034984771651345199420810327304168670235976704426708270671344968176457707557409261114405916868900751036145 - ], - "BigXj": [ - { - "Curve": "secp256k1", - "Coords": [ - 95225479287625109140551300097635441933915975782583911515343531112654602880814, - 113745830257261593369068705146261698861441809650110061237310141136031506190085 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 19909020077923456087962021369246692987785610885502332606764981730113023110067, - 60076350170225224442893367050676875983156697199114782416705437692213004111433 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15656029217860558075932288367874977299995954233140419375302609508233656030817, - 88293512119423239639079954683198441748713533855873639211876694257553830935691 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 15825259379483050804368543653451724857970141958098760943464945060863314262898, - 46510254063758718632499733093297318465018983961512441577134679077369278627011 - ] - }, - { - "Curve": "secp256k1", - "Coords": [ - 101163968142129288084264305494084191253074413300747651525777392366080313581620, - 19458713537429380315587854195885123660811710862685360770347430223563133437479 - ] - } - ], - "PaillierPKs": [ - { - "N": 26862170591381186117144639121800907711621441110694985906073099493104224258631997616337459884349048315436649598594766212786190249139720542986841637789367089751895746802368064104115662988051298443105665522549043623368088781757399812306242052676963161647378421463432813771675598887217547787422261194939872523185392600641669797286300834348740665304662829760721139573070204170902129262797162145018079946053388917283347495995703735479819366865064178966988962612678607190805087224162314010583832802161588455461100682306289046720947974174001828045869589748392310605782826097558345479795972515955139600004112610785604729710757 - }, - { - "N": 28569426937909813160816852590974326182398707183206563780157489308279811863376093908221211903705518704565348072663191903836343635499091979154072341420741676813730020871016039693403607409462919125031372066954550208350129974140220983698064393340951930706962427015297577648437601064168848334164842111410896962654571826800302294766234904003147622246551178854009373086133349568572584906962173774282191211244583738166117722131851467394725949126097483624199330170392292115956857647929895014719727669500452359666570376448590229755339126098108084513655351630004806845329610086536348250655270492083872210115099541350980087869489 - }, - { - "N": 24206147216197161168800749713794253097360175090858672931928135053300720098263302199858364218289609440982336278990382306871237304598903324389321581163067390799950591531027240968685694116269131503639449889176152844762069948482523881916749982047987022468266212702666839762407435492828573898843940379718086699114362935636941751781265771147161683942488081675636897258681038605775448214108367751993197065197897191643383564344845162403884453232776839031251175853763144050201714908798915379664014184087913029794762586324582687266708240565299184055542301695610690632283322864399949456272972805575542427101734659832898527078677 - }, - { - "N": 27422133357851370316963785322815189604726575748114057717984837411771756070272482926958898758576215271907291562151935508777240048370919087691109363558754627052939183040039501310348824807217194423462067796268979252972390229592512803802105741520833681021737552492269574490364955499455488503619050939812934483556240372784852668293634144857453177818024665828049715609921864852313661181061967825839048394234894185931968992541576874445544364635775263264674967563604397356712492758200667296917972566268326712277912968541425534456091226445588857731271210711997226828598037017820056231841183710665446107873358077925757871906777 - }, - { - "N": 21505960474634451313164479453847246698949068816168543450757887402781638444470085463014709362627652554915905319404707097558936051290374460876928738652082570278593089424429424860613076608894979923762290356343173648507348492292368062802168911752824853129719568062188174453668131066706292448200533705323966142811976260936406546600112652090553738417255733994944221554428167638466246670287061019896463881779810197390238307556892485807795138448959345532929528137209046373349550262355661974463926686395148775662060236988349400478971416621513539908477667503550115870803074998306032371456267566517610267867391193312424397935929 - } - ], - "ECDSAPub": { - "Curve": "secp256k1", - "Coords": [ - 76266489189895419469020567248501927603989841769205411177925179985114092514949, - 17959638069442050620236663888410692330316152082152911789514411031446499229348 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_eddsa_fixtures/keygen_data_0.json b/tss-lib/test/_eddsa_fixtures/keygen_data_0.json deleted file mode 100644 index 703f8e2..0000000 --- a/tss-lib/test/_eddsa_fixtures/keygen_data_0.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "Xi": 1123470129231705739242320581717698411230426213735994178302500803173863706807, - "ShareID": 16958127193056753217174896719140242013165049118320995500079788286712215254699, - "Ks": [ - 16958127193056753217174896719140242013165049118320995500079788286712215254699, - 16958127193056753217174896719140242013165049118320995500079788286712215254700, - 16958127193056753217174896719140242013165049118320995500079788286712215254701, - 16958127193056753217174896719140242013165049118320995500079788286712215254702, - 16958127193056753217174896719140242013165049118320995500079788286712215254703 - ], - "BigXj": [ - { - "Curve": "ed25519", - "Coords": [ - 41224335615271381075769974113451208932038734166865770941868367954786737139552, - 13774707131169701307648645647869595844247752878418531713786329629764156867703 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 38390971515160903572427165747410954323761087557985235002455470524013018190764, - 54036280419400883391598155053830219960673373258014736801700705697636583040624 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 12180921436081473618738225787865688183676149452311584940003124609135472556146, - 14304976430285015362100019187031338642123069241060250603697165511151643721112 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 57790128021948066185972365523266757727429683682602823455782373884505843188465, - 9891270332903979021097669758548545766346917176662028553322574817894379911936 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 54411122522958760235689100188515303853105235089211507211432555722072080203537, - 25715298592430735257642280657834596913246686725766124466645327443598871256316 - ] - } - ], - "EDDSAPub": { - "Curve": "ed25519", - "Coords": [ - 43831020110083488052426589316462288057335074484814794644797467442316643200400, - 36043537263710696597551045641434817355465270335317244349166572839625087930913 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_eddsa_fixtures/keygen_data_1.json b/tss-lib/test/_eddsa_fixtures/keygen_data_1.json deleted file mode 100644 index 1597045..0000000 --- a/tss-lib/test/_eddsa_fixtures/keygen_data_1.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "Xi": 73499487457616839495672093976859586345810524103245817354308078351272105414, - "ShareID": 16958127193056753217174896719140242013165049118320995500079788286712215254700, - "Ks": [ - 16958127193056753217174896719140242013165049118320995500079788286712215254699, - 16958127193056753217174896719140242013165049118320995500079788286712215254700, - 16958127193056753217174896719140242013165049118320995500079788286712215254701, - 16958127193056753217174896719140242013165049118320995500079788286712215254702, - 16958127193056753217174896719140242013165049118320995500079788286712215254703 - ], - "BigXj": [ - { - "Curve": "ed25519", - "Coords": [ - 41224335615271381075769974113451208932038734166865770941868367954786737139552, - 13774707131169701307648645647869595844247752878418531713786329629764156867703 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 38390971515160903572427165747410954323761087557985235002455470524013018190764, - 54036280419400883391598155053830219960673373258014736801700705697636583040624 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 12180921436081473618738225787865688183676149452311584940003124609135472556146, - 14304976430285015362100019187031338642123069241060250603697165511151643721112 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 57790128021948066185972365523266757727429683682602823455782373884505843188465, - 9891270332903979021097669758548545766346917176662028553322574817894379911936 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 54411122522958760235689100188515303853105235089211507211432555722072080203537, - 25715298592430735257642280657834596913246686725766124466645327443598871256316 - ] - } - ], - "EDDSAPub": { - "Curve": "ed25519", - "Coords": [ - 43831020110083488052426589316462288057335074484814794644797467442316643200400, - 36043537263710696597551045641434817355465270335317244349166572839625087930913 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_eddsa_fixtures/keygen_data_2.json b/tss-lib/test/_eddsa_fixtures/keygen_data_2.json deleted file mode 100644 index bace4ce..0000000 --- a/tss-lib/test/_eddsa_fixtures/keygen_data_2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "Xi": 5013950077382759940964921645122801576070364469316285943929610121614322332438, - "ShareID": 16958127193056753217174896719140242013165049118320995500079788286712215254701, - "Ks": [ - 16958127193056753217174896719140242013165049118320995500079788286712215254699, - 16958127193056753217174896719140242013165049118320995500079788286712215254700, - 16958127193056753217174896719140242013165049118320995500079788286712215254701, - 16958127193056753217174896719140242013165049118320995500079788286712215254702, - 16958127193056753217174896719140242013165049118320995500079788286712215254703 - ], - "BigXj": [ - { - "Curve": "ed25519", - "Coords": [ - 41224335615271381075769974113451208932038734166865770941868367954786737139552, - 13774707131169701307648645647869595844247752878418531713786329629764156867703 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 38390971515160903572427165747410954323761087557985235002455470524013018190764, - 54036280419400883391598155053830219960673373258014736801700705697636583040624 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 12180921436081473618738225787865688183676149452311584940003124609135472556146, - 14304976430285015362100019187031338642123069241060250603697165511151643721112 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 57790128021948066185972365523266757727429683682602823455782373884505843188465, - 9891270332903979021097669758548545766346917176662028553322574817894379911936 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 54411122522958760235689100188515303853105235089211507211432555722072080203537, - 25715298592430735257642280657834596913246686725766124466645327443598871256316 - ] - } - ], - "EDDSAPub": { - "Curve": "ed25519", - "Coords": [ - 43831020110083488052426589316462288057335074484814794644797467442316643200400, - 36043537263710696597551045641434817355465270335317244349166572839625087930913 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_eddsa_fixtures/keygen_data_3.json b/tss-lib/test/_eddsa_fixtures/keygen_data_3.json deleted file mode 100644 index bd62925..0000000 --- a/tss-lib/test/_eddsa_fixtures/keygen_data_3.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "Xi": 1470810744342610615703696109069535898689855330615299346024505056392105885901, - "ShareID": 16958127193056753217174896719140242013165049118320995500079788286712215254702, - "Ks": [ - 16958127193056753217174896719140242013165049118320995500079788286712215254699, - 16958127193056753217174896719140242013165049118320995500079788286712215254700, - 16958127193056753217174896719140242013165049118320995500079788286712215254701, - 16958127193056753217174896719140242013165049118320995500079788286712215254702, - 16958127193056753217174896719140242013165049118320995500079788286712215254703 - ], - "BigXj": [ - { - "Curve": "ed25519", - "Coords": [ - 41224335615271381075769974113451208932038734166865770941868367954786737139552, - 13774707131169701307648645647869595844247752878418531713786329629764156867703 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 38390971515160903572427165747410954323761087557985235002455470524013018190764, - 54036280419400883391598155053830219960673373258014736801700705697636583040624 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 12180921436081473618738225787865688183676149452311584940003124609135472556146, - 14304976430285015362100019187031338642123069241060250603697165511151643721112 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 57790128021948066185972365523266757727429683682602823455782373884505843188465, - 9891270332903979021097669758548545766346917176662028553322574817894379911936 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 54411122522958760235689100188515303853105235089211507211432555722072080203537, - 25715298592430735257642280657834596913246686725766124466645327443598871256316 - ] - } - ], - "EDDSAPub": { - "Curve": "ed25519", - "Coords": [ - 43831020110083488052426589316462288057335074484814794644797467442316643200400, - 36043537263710696597551045641434817355465270335317244349166572839625087930913 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/_eddsa_fixtures/keygen_data_4.json b/tss-lib/test/_eddsa_fixtures/keygen_data_4.json deleted file mode 100644 index e8d1058..0000000 --- a/tss-lib/test/_eddsa_fixtures/keygen_data_4.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "Xi": 3918092643001693291658368611903051035918515826760101235642894759255531267781, - "ShareID": 16958127193056753217174896719140242013165049118320995500079788286712215254703, - "Ks": [ - 16958127193056753217174896719140242013165049118320995500079788286712215254699, - 16958127193056753217174896719140242013165049118320995500079788286712215254700, - 16958127193056753217174896719140242013165049118320995500079788286712215254701, - 16958127193056753217174896719140242013165049118320995500079788286712215254702, - 16958127193056753217174896719140242013165049118320995500079788286712215254703 - ], - "BigXj": [ - { - "Curve": "ed25519", - "Coords": [ - 41224335615271381075769974113451208932038734166865770941868367954786737139552, - 13774707131169701307648645647869595844247752878418531713786329629764156867703 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 38390971515160903572427165747410954323761087557985235002455470524013018190764, - 54036280419400883391598155053830219960673373258014736801700705697636583040624 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 12180921436081473618738225787865688183676149452311584940003124609135472556146, - 14304976430285015362100019187031338642123069241060250603697165511151643721112 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 57790128021948066185972365523266757727429683682602823455782373884505843188465, - 9891270332903979021097669758548545766346917176662028553322574817894379911936 - ] - }, - { - "Curve": "ed25519", - "Coords": [ - 54411122522958760235689100188515303853105235089211507211432555722072080203537, - 25715298592430735257642280657834596913246686725766124466645327443598871256316 - ] - } - ], - "EDDSAPub": { - "Curve": "ed25519", - "Coords": [ - 43831020110083488052426589316462288057335074484814794644797467442316643200400, - 36043537263710696597551045641434817355465270335317244349166572839625087930913 - ] - } -} \ No newline at end of file diff --git a/tss-lib/test/config.go b/tss-lib/test/config.go deleted file mode 100644 index 20e50a2..0000000 --- a/tss-lib/test/config.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package test - -const ( - // To change these parameters, you must first delete the text fixture files in test/_fixtures/ and then run the keygen test alone. - // Then the signing and resharing tests will work with the new n, t configuration using the newly written fixture files. - TestParticipants = 5 - TestThreshold = TestParticipants / 2 -) diff --git a/tss-lib/test/utils.go b/tss-lib/test/utils.go deleted file mode 100644 index b6ce8fd..0000000 --- a/tss-lib/test/utils.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package test - -import ( - "github.com/hemilabs/x/tss-lib/v2/tss" -) - -func SharedPartyUpdater(party tss.Party, msg tss.Message, errCh chan<- *tss.Error) { - // do not send a message from this party back to itself - if party.PartyID() == msg.GetFrom() { - return - } - bz, _, err := msg.WireBytes() - if err != nil { - errCh <- party.WrapError(err) - return - } - pMsg, err := tss.ParseWireMessage(bz, msg.GetFrom(), msg.IsBroadcast()) - if err != nil { - errCh <- party.WrapError(err) - return - } - if _, err := party.Update(pMsg); err != nil { - errCh <- err - } -} diff --git a/tss-lib/testutil/preparams.json b/tss-lib/testutil/preparams.json new file mode 100644 index 0000000..a5b0d60 --- /dev/null +++ b/tss-lib/testutil/preparams.json @@ -0,0 +1,1602 @@ +[ + { + "PaillierSK": { + "N": 22032681387392825589254166002071611961795510176942284262351871971549670618699536971604484660009625449182459176985688837869302746403719386848879434108617752884985161357302287740438364961676979177489089466179866012617855055796601906324923031751937392609670591187840063042474702098277371020857056255913020470678685230599191986803793390902341671840356957903056675628206862244359901758797593002246388707723144659171073921898765348966425861897392093552324833706338400794480072790177627266223784839002736561936800034360387906580229699891358571200900940853057926962859942155788202124257165274430766284684864930569189930014573, + "LambdaN": 11016340693696412794627083001035805980897755088471142131175935985774835309349768485802242330004812724591229588492844418934651373201859693424439717054308876442492580678651143870219182480838489588744544733089933006308927527898300953162461515875968696304835295593920031521237351049138685510428528127956510235339193749568093261310343052606512412479615377828002844582063009248067854936775372825140582194003076587162162990463407673428857286985415309333956673562821765396825283243844423720411388044350435964681278482963065456881028627697472020220368389679657461485933972028606789754537116337692072611901356418520468894065214, + "PhiN": 22032681387392825589254166002071611961795510176942284262351871971549670618699536971604484660009625449182459176985688837869302746403719386848879434108617752884985161357302287740438364961676979177489089466179866012617855055796601906324923031751937392609670591187840063042474702098277371020857056255913020470678387499136186522620686105213024824959230755656005689164126018496135709873550745650281164388006153174324325980926815346857714573970830618667913347125643530793650566487688847440822776088700871929362556965926130913762057255394944040440736779359314922971867944057213579509074232675384145223802712837040937788130428, + "P": 160193777603039782130097630110310936197073777625824434344069186597213631050367319754974356367436012914555007933030856536542048874131758319921975132921093399098538143025920151565786449823778219011613726394357179754898922359927920505973696945160056757687537966319161224520985379257188052221917780166940603440839, + "Q": 137537685402424400977188059206535944929128469425162029736774561626978254196480032210249963349555471932192933038919145572169239052429716564489511447773776601730968159462859673835222300478086413562629342039899813063273522136486610254190464548582947233304460132255461390661947219789433008660234313361311538443307 + }, + "NTildei": 21052523374416258971278718213757721007333109676938331781826679720785825418493639110225102609556865245898664595577458711956912561778905914435538549163891653045268958265079818585725154962099784288329465696991665928345368538891907108012452248397293908643310851970981400623991703971449863834784997218392054810513673031286710153031380785503962899023400678278031657780202799764261987122007553645946836830164457173279609274505516962339155803482406843697793508356396614178631700503747205161951578795290559842230841461996525798058311724212961582459459027446153358812306386939882611320658432629920356433652975375858991694379253, + "H1i": 8021901126851232380260025530841983338215656583785707477791518586160111978406304886813122737201669207713841655609400144266320064772762506906975186497400248259505415849210040570694824998148397262229176120689345375520518683499672250580921445881252614823447667553303140630121824130391424983696905546938846203535294903425083780462187973177741492580912044664056836244661418579954715138279030399886036864914070796891602391864607449495986152615154560073587429491492620954208527147166400143730147438503028402746532484900288543218094775794963389875856750252475289000102457276885909956975465502973091475427687111345336576934571, + "H2i": 12509717468473818275037846104630472455989570061807260199915513028356227409954301473687022147943970391271913048366929327844294694288271156518990411476986377667409547483939445173891715371881493230505165015573846555327495688870898374966893451210897431375957888492901935351499322459402811204052356531583229655072299466914467645553953633631820234724378498779663433707849959671776763661241907632351601023537132628995964796501155831272786407601785624988861251513091510065427011677984649863319189829205857245947275000756397372039927014685489258405515612224001544801019156470860823519831755614469814278784237550103823971701378, + "Alpha": 11781509422008916377301666918380954189472899284507566138110026604346489846033924402850380143563036638590359321782559077937795974477415555134370249298589903331453627217139204448438791874419416453538872407689874148024194992982977041526985733543618630555412688459112290811871086659897320426595827770072244350441379689156806385273442507504720539214729042648804024188979348957835399230900532221492989819713715625054463498725141857026390103610654906538719172747479887306307753516041640229493804217832148421244241741013467486611649281637015682014878079144118842425727792852543932343909412551798092227773462891858529863810262, + "Beta": 1047993132013754564665827403809515541745175236824687684667579283063123071514754863020106130449741313439479442399886306266759220090249254477246002516572866951204116514940025488680510991320837917042893644295103139441383632830882335279310390801295589057942347885125160351868389148110477163916776336040826803724114000566114527005029932755608943864097620818559701298132698458825166524930923836127537018189784693920438721778334862454251785150569710595727274566387543977019931097908263693743566261476205201714062484298337534064842890256970530183712844906216365176583577880323789596719027873441225062160610399096294270197692, + "P": 69503856480079061974969061235777736715910386400512085137790250241254776030811991887630602244349166624094568707700874998569751403890792645977074865143415454824167605432711585263235724870341295627821805625836840270963459533015174490881877840436230442430579218236266923919599627675908319384408200636823180717343, + "Q": 75724299487073265062501217779644232762774232586132993399009004516478420423214952922706125132844323015938924411865092395944531657327336849088916962753395436833674206032695591709667142099028989550544679381429722648404827304601747820428075531805518000570414892852649878723214094441681178554836350011201484942309 + }, + { + "PaillierSK": { + "N": 26103961668375654256785835449012770324800583559869394928788454726592065570074278759745436655579230864712234249268354875453548269008571366325566138346048316232943045352736537921098158846708990948770983221523026224437715729443597127270779046599378255410670541528038951636994561836492907022224389781388824430902694464368439842589637903114982809658420483496155304678341145282826329090466751209770539414389457545537417927029309898684942665614699640460921478461279474465834171847421964635799871589589984149116643689871641989161147622007510111490536814188562869551100621664353012625133091881886818295489615484191963214714913, + "LambdaN": 13051980834187827128392917724506385162400291779934697464394227363296032785037139379872718327789615432356117124634177437726774134504285683162783069173024158116471522676368268960549079423354495474385491610761513112218857864721798563635389523299689127705335270764019475818497280918246453511112194890694412215451185323474966527165152749237593375337225525681029523650309968416912062943608549448122905932620836150680746619616391220538361839105573238287877713813903861292983983004453061955682166825952509304954743984231176321011142196185293685783184406624705330089457587585494348224113685824825595402591044143466985977620234, + "PhiN": 26103961668375654256785835449012770324800583559869394928788454726592065570074278759745436655579230864712234249268354875453548269008571366325566138346048316232943045352736537921098158846708990948770983221523026224437715729443597127270779046599378255410670541528038951636994561836492907022224389781388824430902370646949933054330305498475186750674451051362059047300619936833824125887217098896245811865241672301361493239232782441076723678211146476575755427627807722585967966008906123911364333651905018609909487968462352642022284392370587371566368813249410660178915175170988696448227371649651190805182088286933971955240468, + "P": 172419107139509555519718541012746372547644336670724082735233001026323850117774310110504081076266549451791178011094366062898654058315049908309071763092473124750464310522900924145315227546322784776719859971112851924698348617175278544005585130510012365947830838164462486430016607473161552448736837471569432252619, + "Q": 151398311367278703812686098783312611421787797425533294985975447975879353131878003414223468071518694724133509785433091545320333345238113976856979070379278755115741527992939800290222710138642754430435861438176495214164881019747461380162415808642197006237615655199853690475703624762465937858790359786421827221827 + }, + "NTildei": 20962551754751728223832615998674353487159412133629744373141121294976078617468389133432094615714371093459379928798207881724809204474897920582366637643940514510901544181208969319089878766965636278711400086591282529548335895775691829139799763858556042152149253868470797894402514269625885059535883814579895539572663674626628108602754585629543129531843763556953320310359571522884862716925088677496098844124667140184110112543267097223965921005761370635006424228732589020365762753093226895145242828470061890267793327923114476291890961096185060711765234433336622875030165329580164494842021314940993235202719640032782235794577, + "H1i": 17891687529017852421161986796152942266664178361950367848423654738245289549267834562947653891652997277190978507489809773147203716610243039514972694499784877740697653944332182702270781627738851291995930859750413478173245364703084115710741806513381310226781133473729375606489966173247420876257392752628290578283716873104244273767109415193660209371520607256603269572574788296836008300100105019977589836104356461335068232424640896867676041905056842065466989250063253196016710662257201762401289441771841924388026608032285179009761523983611215771408833027452661477531595845325493860092579331780068201933907011996776700204056, + "H2i": 7105557895470594118776879847246109810092156164266731522628315775968009110525433119655845287839318691162225575746812148658864832201304451229203154643205932999528634564963360275860664202404305147267146917239310024441847345640691114861779866262798511131497496552230770228369902297812491551311172069512533218265456720446703770032344167630760305501687734891316381563760078704494199451350905500934511340084401742759434396756365456357480962913662966556828865132676499090140185620160619901956023968102761548268797290288747768974491377318246608216749915808906725014024054547741664661223065126208283713091832766584009897851912, + "Alpha": 14252867114905443460266463891400976051966013168800524308619102428474397355481845473744406470664497277675962237379943066626373904834067351285662036202898185412082941312333862898451730364274768617037638598720690737258419996069842596827107171072804097227317762329726211232114889256143809834239192740910258430651277614379530952612901828075439027708875011231749240069163905750213331244417333305810335269206208185793231625999383730162802111149609088588272728381960988826168493227752355406453217395346202893126994852771381927065099551988279074382486890211944156066290958803704899236205136289485062625239733913120833491438619, + "Beta": 3308477601536449538686166252362646519422957799272510470045492087015704311807812493278640139187248735483806843131297885228643962175295892486465619687490938353036408077176590199877976090008307150939043347379678036101109052327523501557634216520924962259710188384339883645061824969396528097483804441367396204838242771047166493455177136724199301563861057966883779454552675707159238120706111102386124375541184282083279983552088370568807805676770285029262285236302230449430314856463275281156205673493227560462956570923884706215109200568587289211194318919691691075823855586679724727157196631371469618780186293983495059736343, + "P": 70058960799688057566638526044289506919512841006990883704818823739058950488771071829118710561836549353483249532452003782056045357972705141393632336058865491578432683572072392504299199119762747571996889494742264646996448262664704698085763505807588148363607487762245835841547130020014878898623974346800466877579, + "Q": 74803249703801863468321726931457189115947920748302204757078465017335878850255515868102917776180277057317207211099024163749781927285857741070864963322967553574541575740407431582538206772941200146797750917842591768148280498505488211533808969270143445933318751356309388889526126153915398169889021689673467877451 + }, + { + "PaillierSK": { + "N": 23325205227925269234966831900835479518092306244833499095261694235596244231323872359308411977519955992591209944049942853108161557930862103374786044665075872815753771225523951724437713919174168132257652949822169429515394908975335444320395620730848200991695783093123463564262980903896490223036659773976952573394729960836306076073488806770990715694767975908880837452504749052379568621394898065875783943237224678952355613305484983905867761392281013454017034625608294097271017440060719729441016257233879881980789738436305748104466410983385589110989500537636737526939724889748108479509960189543769107525416068207577281095001, + "LambdaN": 11662602613962634617483415950417739759046153122416749547630847117798122115661936179654205988759977996295604972024971426554080778965431051687393022332537936407876885612761975862218856959587084066128826474911084714757697454487667722160197810365424100495847891546561731782131490451948245111518329886988476286697211712880632111761535343366539385588866331097819836681771447494608447751994328436555841843596624346445080227209576723998224222675375975253164395390398736410938918652865114821652738543486923855299177581673032682318678455801556036978280595322890239724336564170214067662563010358176242514130409844303826771418202, + "PhiN": 23325205227925269234966831900835479518092306244833499095261694235596244231323872359308411977519955992591209944049942853108161557930862103374786044665075872815753771225523951724437713919174168132257652949822169429515394908975335444320395620730848200991695783093123463564262980903896490223036659773976952573394423425761264223523070686733078771177732662195639673363542894989216895503988656873111683687193248692890160454419153447996448445350751950506328790780797472821877837305730229643305477086973847710598355163346065364637356911603112073956561190645780479448673128340428135325126020716352485028260819688607653542836404, + "P": 140393811183797838480821906981452589420195411605633028540770946408190278531775108359323627215540508843226886590449120098918917445439766412940054444941947533374733870455349519451843339338884553944008926035822510522426677956287326530248527234150950297839523861854685125196139189091902708825402976840244236198719, + "Q": 166141263858054711937298130930491927615118301635531060421083116754482838874466084404776628828435477218968272295882415810500398596089296534748189399868873742018446263875140566683695830921147617438425649054417872944682821423986188624179782657705307780427072687465288029187800284099381370439193402759679502059879 + }, + "NTildei": 24063125973170446041881848860624212199403222891269978377833700020797999159051608843224512736934618633222527679607502628112400120150711545859322771057937134955171933207814985594883491372433104898543398193213899332781156243190668067243686370991018586287806948152272231283689037372100075783891486765705146152958043103596575551428577898057190586543500283311190429180129106035783651392594198726324830749514861045473143471128976159097904539324000528163153243809415908369537333105414799787920817301498891289856797224635264435540899479902709869632703726622701833982566124943366465226336103255383089119350335203106822915212781, + "H1i": 4252667289544615396295234358681340129559005698047823563379073045036163938655902860749049217982380377365223510166456638954386973542787766939700921406447677890993681530076950179183079589309150839662953548469596508482901094520996167457496451009454252423093053520716470361751316025345288967580599957461030917817152909204038507869302396913186243074540871775001099613937181469732120556451198315818783539076115603520126888406202132158095900348622127267327298962556485343299134596430070339915384637185428849583176169343199373403036714299309357839990291176606608216226926277870223276401427032852047006558172680729229513177117, + "H2i": 1769523042178449999195644558894903069126428428084272255251942147339573090182054514450431408133144177158367244251203972310078575625459268005475013633456379458105920858500058709453232758538280721954079465954457627505470785905947879157770549078329594719704981105146079898451796528801552339542684188613565638748213055827431749014582883377409063429593840491901349398017447549473837915085947537144739382934769495498491993335727916394058586319812028051512055086836516351861835523722109852903246757437463194658040354526690473587931736766050417825790847665614359205294258644505542435237620366532264766041606438821620951967663, + "Alpha": 21111964989079510139986592923694765231789226375036434129654330227578162066579617104686617462346607253393668951629598894365476419326938691992033775402545144522177982018039196366371398087338564197277078110023243747936580822271167070344519764102671860370588617429792244651260223540786928714632935650156899525255665897639695627666001190244601940150268534984454794487750584705290458366850850570454807688929895016647268357746175655329792242070136303154643458130678283838555340035684167028343178150972950950358623806835817746381459834788085817808072578134932259768257195064820693426664906997937436179610417969973178015600128, + "Beta": 2286102170866173920033531133455745277469341691660865279291739273898211446827236040594745771849333978517591580773342729850666235159855606241523601131246870067326298810695028919639322503482184076319876281111128712445178160946968658343137564318625153578028826448172079866408772511262472474830430345842724390506192941644127287634145291021791940292500886319166869989582515855132962718923754281751348369256225237205668510887802740820278895233917695459358695976393176439038359038656037126380515277536333458692936817507926171943678200016184905366437480561577283575228529697297234085593033704593882508939096485126814158427825, + "P": 79114110889902046575604303871012753682326787862748141890597996315769943446722765787583228134894029563444114129300035560585563846855362683552756112373717297135950622783054480691603425705634636931500470593427005599027020423835674708543611706731824725434892055537618336440791740654956633376367333037932480182973, + "Q": 76039298497133876089837239761864508901571494421106969033806513753093239509449368966736828738454800670259915363368456883463231588697171482576434754063389097591306263479246257897982507159326372850917042172117141315986415412244756510258301246592233895915374893669381045066954614949408758366382011430563049634011 + }, + { + "PaillierSK": { + "N": 24226511361144744094110894899604763482591842957796104016638816164865158900625300778167373362100531443821235120080053306943906236666524449187729888783138788711875737904860285122266912375431418748606924270359794150789457586652503737031542147095967298293317976041243066245794409801176460609198578381613091841939222415197262381903503170096594831139404771868828212572141056009219553628308209843539502929267476702668157458816638204847428665649782252333362303250926410134507918088259320009037262693059595984867158702173915692138767179801985693428541122053696087590919256521962154459229408262162570931853101339791228970484581, + "LambdaN": 12113255680572372047055447449802381741295921478898052008319408082432579450312650389083686681050265721910617560040026653471953118333262224593864944391569394355937868952430142561133456187715709374303462135179897075394728793326251868515771073547983649146658988020621533122897204900588230304599289190806545920969455174212873058751563367880620586412452252807853322389244309428964327933003536753229998099887234564346065674698335398696012799943929444899816035105573037845377206175257530039147546723853802021722284166591547597482691413109478467302867808171838648654741992051027809451558650173605284414545187608330777321710726, + "PhiN": 24226511361144744094110894899604763482591842957796104016638816164865158900625300778167373362100531443821235120080053306943906236666524449187729888783138788711875737904860285122266912375431418748606924270359794150789457586652503737031542147095967298293317976041243066245794409801176460609198578381613091841938910348425746117503126735761241172824904505615706644778488618857928655866007073506459996199774469128692131349396670797392025599887858889799632070211146075690754412350515060078295093447707604043444568333183095194965382826218956934605735616343677297309483984102055618903117300347210568829090375216661554643421452, + "P": 166983550597135694677295042364120538194351068022193864614902859559729199240332299305480083766845256707531539489607636494638151104683845212132861831960863133729769719848383654551358754812454616138210425249710339047442913301472681293678720053837218796688846506405097891210756024809692986990170935142068146852303, + "Q": 145083220919128705699139292989537776305915185099373929037534291731168563060804037774026645726162317268494569930359770960764914657239517321597371207819471310023736017895876276190810490539537325284379943741110158125941440281556077529126785656181571484746425913501437664901351890142309115772555187987606180210827 + }, + "NTildei": 27339286075147215643040809951987723175163161243008913019979948081440585676858405873493540624998073453984661239078374030794487907388443665149050246122096760296507175896500292691497776336258229695229951054819526521173467785237599580756587421391481124065022772588139569945998577816383173900620687006684846284976926564921683136889056388384077458570308312106992591106660711942688821008817670027778670692365091235462900209635415765784855983918908163114366056759683577008897085980723740882412258734358997280156671124288447785361641159599057006698558146654911087066543834860299783526648121237873270455617906451482814775292033, + "H1i": 3461013326772463112617306001903730979189654296415922609288334284665462228898075547230412123200445927043096120083845416729937171658647712744087911369884014340207525452537835293902924818558756084454755860017415323439403456814384568821062047640367696084316762791005536149939211654734082178675355461625201699075499235520382853887949943170441620761258549869390475914468851340411118311737864428704518672475625416122257196588934902812279539840077408455883935055022665403342098139991085364510145217415796572546898829930860363253718161166118974031312746229987175817290762178424229557619133264604216382598254175458280089002635, + "H2i": 8322126016246789583982873082848006376261470487894867719706259748369213614435115471185039876936048527363454562623166093733893457294883939824802412221922408873971609513701107583907207386818180203918474972745521470210059679125868556875914234722694356168565686310097753362775535461421486379582176841493208859172945730320643515629774489539840425814435950640747280796438490990823026960006707118923268187128851625045298256979702832963711034584783603491543860082284186511560998558369036629673232130820281272262917481201339102008547572688851505544966670756938593054706754429034877938281771981111504973287640780356734874781455, + "Alpha": 14413995018156907647711998489344289985298531961129879503474835642367814456597715671073969991877626677416537006931808110698418694181095500271438342781252417377518969210083888088915208313503970772950468596812780310368544913589562619593146576381302908453935359218230578263371911480573916995601615884869458261594377894567036342430642134653814989048323215003033146653283530620877903805635445830080794500803374298366094458011072024720772676049976468530568562660433222425396465849755174221617198549569629702729765837550030945047096713111289611869665431921811632070116122763925782204805411287525723093777728313975236218358918, + "Beta": 1330500725969461471421840390984442124157542903012996157331511181870198607187050218243317463482019716881496675565018168275103630339161208257899421023813897322580081910092343091667510408817032978584878943283504493499140231495200277296112803229477223503329266339280505029395566330134033435716007659411594218791366530470041606157689345932997637244568352538584533510431320525060329037260326125247916053113396876638237685481679553426350088825710694097754242433465223532648031008655627862057348593139250460162864591552212650411083026607267555086033731448578614268409080730471897575693179091660336921216828328980854321318873, + "P": 88956867866820603258576921374104964002364820318744886578631656530978611541901875424525997693257890457437842849196774467465085681270613788362897457687412769970356450550185400803825337329739988372745551032604468593802197531973775191007584935593137630129541330880714555197474212163677069137887516645213401885983, + "Q": 76832983025204689534493982309794851303769495257598993307864963831890659852654197388288114470603833988775139906179109969207383215985533224346196774958340212096132713646083940895183176187204420256299482631384908118447711192486195166754664047570238320608084428304675796337948687959175934628918694986977652195999 + }, + { + "PaillierSK": { + "N": 27105461894349183309000812385368493637426733505264052480072119319546512303618874411378402805169727463164806936750986572528386200156936676894890080365445014999196958191169375196635860212062931831170892558037313247465057244755272101122558552019317433228619357821666366467985158094501036413997695521607117793677858623016773096796815383764979733633392436252143362156513254589387546633261564820084426126742222583720853005859696533126654639975200636273256007286633158310777388538957502635387387355124020592283261350408995077766779351168155117861243450733106720613131524819294664079328842514935299345835018731284903782234421, + "LambdaN": 13552730947174591654500406192684246818713366752632026240036059659773256151809437205689201402584863731582403468375493286264193100078468338447445040182722507499598479095584687598317930106031465915585446279018656623732528622377636050561279276009658716614309678910833183233992579047250518206998847760803558896838764566408586139010696666908146601515183652550551591345838860405107979219314198373534626227948860633900645313690052145340761161511409647338435828523705825762172799003234259439469260332849759618710557536169330148636314935446085524106675311520493656291947832169762791650273754928276398713795425659269191211351446, + "PhiN": 27105461894349183309000812385368493637426733505264052480072119319546512303618874411378402805169727463164806936750986572528386200156936676894890080365445014999196958191169375196635860212062931831170892558037313247465057244755272101122558552019317433228619357821666366467985158094501036413997695521607117793677529132817172278021393333816293203030367305101103182691677720810215958438628396747069252455897721267801290627380104290681522323022819294676871657047411651524345598006468518878938520665699519237421115072338660297272629870892171048213350623040987312583895664339525583300547509856552797427590851318538382422702892, + "P": 158788085959761880064950589553428809304097689194484592403394790846272833648628530830519634638771714082418120334894159706359230745142508768234452429219922099906397173786804331828077274545079808950139032892207902730659152846058182223632382910790077954115349316484092040041827074889581946516262790567489956705967, + "Q": 170702113641056895357099359133101793721033461845694872432138988325315360984539542184654036205729601837144258144698082738773086207238832828149897810001584686525393358702179424620789414879421545912007245178126877763490327429925887424260444781329330075120511163284988738739505583492919971727904622179031402825563 + }, + "NTildei": 23691436017855427690744551925680675751250741626421676202507912240685070886624505127975370962794424815402470982063731900673714286217600943997284523150588911399323557404444317717883078340523175037661371183111219631362366992229006006220783399355107104502226910182244158617543778049362407711940835675954357455142511938226501821950216437105254310159134161714439222013148809846710260323775693624459468062552210121052382247678518172694187328978075519468879973412728895399675080384664498095055842545978391442980374038712653280030532582875548156807629170435793732243596385520898213432366953221704775007818824521585883959203841, + "H1i": 17932193002987671574495441469409127392370151543929270710351635414221934734562809125624243906810943108503967405005828654232185330119701540260824878342500666498535306144136372526015342340296503335394172410131336900776171942656160842033785839742979772089804272322672695007020119040909512697788132115871307948965619772340555262326363558343641873163576164000204585700653067269886421147844891627786467545439613998367235754360745740779037900502062630533212555287083690898112744174643195724344848814257174038939713079456786818479580505563351639235638713029134516367564483951764900764048341146360703413290969640134091967290275, + "H2i": 22144511485181764076378632925055859554517034281914321537325450754791188531438898011733841223669386035295388616172347057818335638121559385360966413699065274132284819173472900569012429525374927738572545597101140946802265126843018662290567556996779559867704199901918249942568050111783255047381864793539862698215895443308451471018069037594826987413875138189941491952651763391969551652771274778053252888595339377841941751657170177826288275027425903120808102958067955157688362334580580616687045142103438735764607262106361548086981307576645889657909348999019207526484743264234007721605934608721857264017021201801228714073322, + "Alpha": 12475454871977640533793742001964509717030234369319054761283713096754488025759647264617618667471948169707595268964990569463598044205122390140472875183890685489014112370431556067320597664541969687785175940710114453712767214199171556171508500097985262271060053417665005465398879134264915521128766972590273506751956916658661495945567005646459815432560436844474951445661121138145961292832389878405254525744601890459426832794315879881710578610428146356911396453602498624346343946747856118322185468467706906642669443812238287626221679090803160411080703449986762292725838665480654184225731249142079901455593074852687003407121, + "Beta": 3347757673070848815750707814663538545831756955658217870201384478065575926254131397933932861321310014073876162883389033326792388023527881801618972406965570525406692560066937269527681500420902800339132659175307730861124433627016852213207311176944933546395986224251842303851284221677748437572008633275917860849146067320000067525147526929224843434676175296387001628612065916091898157803746507708977354464618444896580512294214469637239942495514997184825033934397898996042157656544219602859177335011399755115685998458424801262820483385480035147963499880253328287061760124677500512068646187505012636612192709673877113813776, + "P": 82523448872461885545342850364161285845198510758875532944054217810743763485150649436008920479472261720115273081343702596921073662853817491862139806529369649415859578315023674101391853182691852213138751532233140788368741920415669029119339274824835905811640381098821585768098859128301231076229752922643669756753, + "Q": 71771830738890965234415906767871272848484115061921410007753542465283517419097330028056337315167049112766374105979466657537800615396370280646178720246754836375136008560838529382069672777436860683429661803464272685067373809575464139727489809395705517046029291986631836806318070281387838773315000750346147957381 + }, + { + "PaillierSK": { + "N": 24210579506590879595415817848827594816501513507200083164689498948679986232303302646732600288656128886523560558773695824094527846112596017863955871733258029963186528485033611772941473960967926900728268924074152719281076374005063841643807751604681895330398696426165543442661663240736536326142637610665723927976773223804704133617358537502650826107573511813956294659639755207395820555630431703848474826839841653173493253693385559890333059832962249252488665194632904458168785548708233660058288020527585772053436305336267609027126311040477485119240509622073303953527902918866190679485955288565964845676245553763836894383957, + "LambdaN": 12105289753295439797707908924413797408250756753600041582344749474339993116151651323366300144328064443261780279386847912047263923056298008931977935866629014981593264242516805886470736980483963450364134462037076359640538187002531920821903875802340947665199348213082771721330831620368268163071318805332861963988229676722905976830190080433905272301919869241900186224400838023703593016549060081520844813399605374355537959724918817750857465190998572126418846754334344730979244444006673618857816570858514321484077497938564152559439169531545338833054799625616507437091391254134942137438289358574296712630712452614972137363638, + "PhiN": 24210579506590879595415817848827594816501513507200083164689498948679986232303302646732600288656128886523560558773695824094527846112596017863955871733258029963186528485033611772941473960967926900728268924074152719281076374005063841643807751604681895330398696426165543442661663240736536326142637610665723927976459353445811953660380160867810544603839738483800372448801676047407186033098120163041689626799210748711075919449837635501714930381997144252837693508668689461958488888013347237715633141717028642968154995877128305118878339063090677666109599251233014874182782508269884274876578717148593425261424905229944274727276, + "P": 177381965041522402160061665459054923100428177320810181945981375184402784271101698406233454313887906522836987486034406428345587150387649619078234925994813088518730838415835760634314798880865706359307205178775870401344284610385737551430222207243332359340768362299438682542454230867680980712149117049852277388859, + "Q": 136488393850657554818314969381226580633345152835112028892097784804231738261209842400551745726742997939580346757513517960272542300577455380572736759969401907691565822279050661708340079929691422725974104280363433506903687367001069901700688163596956720004352048296867722066922340549690439702671531484040342267823 + }, + "NTildei": 21825923055692363363807856814041788297932352082686522049762479609248131031493209178616315332678260688081237002473280502673900897153728674074250978920145603272890375554421010544375045978230115152148635406266868721849462035935066549485007148826731070427853967064565478034197086793128579348456191501574069197527336381271239431882182590125002370090425492196615622157373084894744370877981651753517739740180746953455122867818868889767667533954285848650265342352648994696666663166969311372855889865099834423327240443645946623500446653775668772232699108591681632208777141414261094814249472706286495282111497969140396482021361, + "H1i": 15684164076107486362647627086189839256071730816921159825587044649382702813353249858805918238913067574430611789985157531061885721123720221782927684432970928907539621363773449598241979707937789782663129224896054270014808240880961575531671500976415854986289417648719437211694365683294130280283560214173079398846590084579457505651739766782465078556211119540434074200068804614435241712280915634650903672686377877661033196824732485185050823525529129460360514976505602179125362017513656878633359575448869782973794459491323649244386533565088224614927219166490439963649314544551807575603747528826184191141107064431052311814111, + "H2i": 10937957341620608445027357120052929078414141949388811150248709043071998593032641885646815075674116382573176215477259278749403836199301249125992984196478438343573106510323359252348218406174641887390259296850122243033119962428309996387988726358998038956917625170381238080857980422489012499771805748574379337089815869140942326088225688169969240362341247885407274359457824667272277477820414925510879658646557925827744040438666460540701953969793123734196698457916742617898500655685277219715696012129696592052086528807524033129077162474417417876027343037811607066274564941807607132572606056869032244031664105944082462260040, + "Alpha": 7382441603778981789049097286373899782763514892108731066297172807764403988882209235804328196924961245758712156211586446173584232172348758441051517953970932017638801228579942905743888258770393992428069958582875754824949103973366006926096895034187574862293030891755924520891887599837303736784661079762915753107874045297232748861192090206230779111716801320484889817963969027040956364851122145910342837585698833070404225184905222895161394340456991918300671707332063504510276064035857308120399388827534382418618440504293632241252707321855824914761827312225109282211684898606819593839303057121500778743615359397457034092913, + "Beta": 708436051141781127878868574422688577554367194479729534264419571972132658534477208665290561443956154465618358950511358859434190476669625127041269758144450847707027420019028639224829761202087088484160374252672258067082338470665694336787011995891137048270730792257395310734540990073420042289150127555543196566554711366496575588711628921909577889068884910521718203148179028215188204631432782654373974910760481598092652028192675763936883220551492979305102099548768484938113748450314318866586754316995207932168501725692912507398907813438681582391117157798875916409585766188767602969971902826424279053520482798830944265880, + "P": 73905698535655586230349346093201129201557167554780256808221506486306575694672676365166917557278592197808755100252284140420978046774991776975293443640409563621385798103596241000569285453894749792866306533028412764860475088073668106682198739416911275855020540110986230668538580392164176039576002085621864023099, + "Q": 73830311762639355793188275321701655294621835018962284029789713083270057112087920473550055750699498154159713687587041798639840638795396409553202501378985986665932611200697368494143020850410182216600084587454433425689098255729763320578480411408541235337848628812709372129035207686743609227178425072166271130219 + }, + { + "PaillierSK": { + "N": 24322215303367550905210110765174060759809472178609848011900853683380085516442186455124271929266342825348559686043500955269265930297750350188223279978554715682735202276928354304246204851496680784667013660203145613698997290355302794883388191194275396900942884186325451133403043288428790632928612676529268980348146310180898663977342668075672748773256254787902933156297712230034266021174686185315276225674528280984796363768987990751830394258812264069408824673612104894624676015022466455561072031894010442790059982741264561513834032302374674652486521382708574019730969187102828218483187779489423227024825074885166607940177, + "LambdaN": 12161107651683775452605055382587030379904736089304924005950426841690042758221093227562135964633171412674279843021750477634632965148875175094111639989277357841367601138464177152123102425748340392333506830101572806849498645177651397441694095597137698450471442093162725566701521644214395316464306338264634490173915869692136837075738294076856810260292632197426285178013579202293272894294360440306544298444750341896969593373105936387103451084798934421995104901165470748595521592117809788279932397439473163397005408786083322133772539290269046960066503169281554215906500582776045218742347985521544380157442156627269565545138, + "PhiN": 24322215303367550905210110765174060759809472178609848011900853683380085516442186455124271929266342825348559686043500955269265930297750350188223279978554715682735202276928354304246204851496680784667013660203145613698997290355302794883388191194275396900942884186325451133403043288428790632928612676529268980347831739384273674151476588153713620520585264394852570356027158404586545788588720880613088596889500683793939186746211872774206902169597868843990209802330941497191043184235619576559864794878946326794010817572166644267545078580538093920133006338563108431813001165552090437484695971043088760314884313254539131090276, + "P": 136877526817588181730962035264559857243502564114609352610401455595289979390777578944484265568859428722136778378611035804609100218759361481869086079762491297117057525162593904102460467651821449388783994365542445810242683186600354206877457303276844996569731945051239640374264566775104838809665049725202563694119, + "Q": 177693269807401644135117886694568395427487828935753447660152369852430253195187725757703363216168168468720398644165082173014391870455033743549528791518672100316575305624252974898746769363242666607265170803555471436046270535236226525476057740868620591348236076499498140624227241671229627900275711905424913155783 + }, + "NTildei": 27497108900777725727943201625139008849102931022530537483093014533131531722651541399684618860000157145587008904377638733268773348021664121792851954996533085273085495560279031694720711084207998428476676522230268713348371573024058605159755832823734306460617375660576683401782139459872359159178345981307664968203927546979252315844487326577325467173205249032327729213085123724468449732074491270897213998196562151498338923589825574370637803940435864178801463898840165952581858265362652296033880682706345688479821392899092230186653687701003674684667123105747158198612021687738087468561484930396372459125787723101873736456981, + "H1i": 21346729471241227353829325240029509476402550080017210933909197858833364879613431301292805330654979203140234733083720939054865596901217566576992209746790722941750671985357643908114293587068186876212092767141995337558381088546762770427026688341194823384748480151633125365521603849082227158287858242841513980434241777312228446476280998030933540237084294011016142841706382912572790857702759776494964228451362332325760993364320615057957059793429176241225683506615982542898486322656113904522241790564667788547860353350406711138697809187335779562476662654995219586733826169659545503981626770715163378482774885953498883957691, + "H2i": 12771862802066948874963858131483480937294668868300800135102905315484546586075858318364123148739557722495535186135418735753341303582091734305231344298425670555530384055380408236043996167596444797576589439877144874859862141455176956503252202710701994934023394972205689090738225431182150237620689665508112428149309906821872259207478340085425082172342241813241167104154346505803226938478250581790279871536139999834295400736265401318045386518147347440182519187979059701331607320416802936607930843217203167316922652725011502954309035922042107940404209556488808884356651391255615441835596279032845362289013867575406501827685, + "Alpha": 1222657933149133737786041212173211386741038246314956260446673928726028348671736646953311399385644289270171674551976597704642978669509879984539170782174945060979155772075239872274861137841746745183931109538608650688835352168473229387890908313345681954747076497873114893004631507516909862632335732748874704996432343009427040226788085549213712390108892922264937314220438530330367683149445790928829759615854794533852996554825296665739416218080587678439405736360016866117357999498631948148509919603380984304242817553333964104339748444165511972781118673272557520616543604467903273592237258785476061414081176127083609334691, + "Beta": 2646462814138752750020121583793941474170228657867677366535470651616944806249189517400474444856544343404232671885702295263985413717101959766957790638385238514685784380850232373820367283100320078197266850997300405722279929663278901685149424660354919243625104524015520276272707859876015642870614349095645528734153442524657081382069817549676738869702746887804943929734535670250833123979322390475321261975804364428759035738848874226140439498241427804870111793101984721448971470970395334958710763045310189498969304828652011076163730486568854058302983884785075204847110249402268710501353242834866566717225514661649507000758, + "P": 77593370979455168395557239848435040816220037251256903737538362355163564570184066753549744543127019354447391190078401474830848248339594411860428788762903037388068490569528957274370767081602598161509743315026951897441668428554966489095452490387554101386615467337396261984449718212274997186461219511649789904233, + "Q": 88593614872262378325659889964549995339937221719408679957332431421692600126515700349569605613433261770900044226781047267829173573731523231925716537287356604239803047282305690539563611237400245842950779085918924194353729295303287397383289930362572642076761100978248822402138288188721462208058698633544163549371 + }, + { + "PaillierSK": { + "N": 26405387206910894117205086294354246640976260482892374862320711391831557024085488298362593032510502479654047456662880765264859125860149425444559417662542287050663571682126431640513473238646820791279640739202987401352457478833885390436121679020359543926130790525072188820324703113537629026410032890365515513677900245329062309272555246825763917111195592052209023783548831694431105478645557427816564166441715897573751581621513099354037849551939416133205893554124030153570413444676371646855434083564732955755455974741393227741248659863435338233056640853169482895367991487028793858447470082933350955390075499879793315531337, + "LambdaN": 13202693603455447058602543147177123320488130241446187431160355695915778512042744149181296516255251239827023728331440382632429562930074712722279708831271143525331785841063215820256736619323410395639820369601493700676228739416942695218060839510179771963065395262536094410162351556768814513205016445182757756838787231762630180414289834905358212887386732498327159103281358454806839652756928603602366067381846350827801582660473408447135693708863061080896988514611819573759047143445069191933162706318470142965731561174297400421967766511408664101636900244320803506957599675546419767895237105310780068394580491841375079944778, + "PhiN": 26405387206910894117205086294354246640976260482892374862320711391831557024085488298362593032510502479654047456662880765264859125860149425444559417662542287050663571682126431640513473238646820791279640739202987401352457478833885390436121679020359543926130790525072188820324703113537629026410032890365515513677574463525260360828579669810716425774773464996654318206562716909613679305513857207204732134763692701655603165320946816894271387417726122161793977029223639147518094286890138383866325412636940285931463122348594800843935533022817328203273800488641607013915199351092839535790474210621560136789160983682750159889556, + "P": 151574598829656571506309834766192962704416055103298598243509746282585492326683529064741306452907061921919393449255966971549704883979793554126255828983084687384911658312184413018878364181726393990420382385862049293754923305635942256215666701531373175321518798342933078582360870070506864019271816114060039893503, + "Q": 174207204972291872469267180281298373717711000451406978742605038534840680805016691547090725225116133996229022851310315488216757250233500417285660695917306318667407499474048849970230306746066275833572470006936377603558203534982067773567173662996502706131273337593021244074635002241283954581642700082983115748279 + }, + "NTildei": 20313358558889897820426530401634602876114284534284053122141742845485266504290495921388303644815355815840285094208343611225617217498355976100618719490273296554412403101105676169925608992228311149528165618892830290880853849754817647042112766663544137102581786525380078174767390186202593552247142160925524241616450810776408078057489854536493710576933458614239060695424904361567472240321945899295472212916382244989406650943311772566640490685190613590084387813921814214848168130025228068305538866804240120971290359944530794356410458473864004968706726209335629590404266409745892726461519824037009473995213538176916459652437, + "H1i": 19976302334672726376066495285754719570620788166921910544818957920227256819076374689278241963451430217338124191882358103002871647763201505354597680111011306635139418451938783836583979570103908295759137034100884312416135243009276524839814736647686843871432553999135898638782478681335395765387380411541130423150446761341993669599765840047682725560299913209344663307856115518537613887473966136039478547655800206219994750579788006830927973451600503281088613019927577259451349644910748447941121592693725852555427688127331543617386638344229186651119266666080999968600901224711990439406228806399678704297048981044635144473475, + "H2i": 18631405280291603937172443146695452440749769146759778074335166651065821884484819708951819300228977419365623981832401378804876174585505214320800398630630531146206615938924788918784931309698479344598192616825219817572674351668005842694350127549903303670459667115528741681742140008697786885393009261004709651694589344002651700504353857667120687847233240208984142775131235334873789995578815007148884005078809098382179933251834318083903999521556633688887866566026414033945400876552289057714657358560959728384089304049836627433179548597930026091575276705808743856974141099944502815867108410421424678647325201978292571161363, + "Alpha": 2730661158632756560611314052956645711420878372401360554406469893275441022534446460465422612111283028110115050500887669569269944021449207527959554411411254199479134724168696956819140143910947259601860678666029320064405592306904046147583116663433572589083053985914655855406633545542443586399388360692546427457001155384320713066314056302840316096200269069581379479974875855807236163417802525418682027505301303791573782921228592044857666146948234229705569965343888819412539557807228415390687595116628897908415580352027089743924613385775139343812646145829596792769026407063582455040755892638534276435997367191728939876460, + "Beta": 2062175012385805537442127411524423711617301523961026175569207074738938672588791865220816125321289973526136228328596769123634519206128240284364541605046232630842631304310645656494919559409548548522840259121826779938111620803297245311503922710337190471093489286688621834742331600613512015062725917383607614872747292588904733306058652323975937460012224633093813157052155943473964952907006910962219394076584582068874483912450765598802951724538911398734624720155606445045215576888150119305806413059705123844834343691203215265146252634695828999581057604775488707390713741576587496920955633103007202130050617474249091089894, + "P": 70909461908101590607059282930954972121095273800480069776191615829444922668400326389669112012690299620000264181613196692272898022301452164027898548232014369759656337665489671742199008301053605189093495157555337910509002506605118072792382819709640028161171191936659294606554687876789990798123958659751165959729, + "Q": 71617235599728347845047202736174520918450078071146602467302052026303133039157904798881718813854709925699814557792601177985527578479711915253460292064507284749952701335248164772549806706414334707199970565454797983289486793476446127509893581482577287333670725324876617935642029941468101713149702142803183021171 + }, + { + "PaillierSK": { + "N": 22587155936009461495683845337009644427985455251655873901399124810358451827820120570495002462756945466937228417119258643199984329619581338037827366424504626413973345269633865749350596900936492815913675733864102018565297945571927086535682396949692273791254572579126732118672518751661509857425298524229756115683514524246192888498753806428412631823063859212898488618466052543126660100961366900844204698734540116918141657632672870671928767451329597683095873984777722119683128704294128809953302349136317872570175339662685889548027561948264235939854374573029872654479603112283353478191048181800886353910844577664011224136077, + "LambdaN": 11293577968004730747841922668504822213992727625827936950699562405179225913910060285247501231378472733468614208559629321599992164809790669018913683212252313206986672634816932874675298450468246407956837866932051009282648972785963543267841198474846136895627286289563366059336259375830754928712649262114878057841606728708789840328877751817529048103105162778614946033508658679387013483680394224078892505503212142791456312857489678891868902096524941744052321894423763455564066198200584577639198770513172288524134359942977215364283183196965377091764600867337240053101603231811645009681656489542357739325170580611903626959598, + "PhiN": 22587155936009461495683845337009644427985455251655873901399124810358451827820120570495002462756945466937228417119258643199984329619581338037827366424504626413973345269633865749350596900936492815913675733864102018565297945571927086535682396949692273791254572579126732118672518751661509857425298524229756115683213457417579680657755503635058096206210325557229892067017317358774026967360788448157785011006424285582912625714979357783737804193049883488104643788847526911128132396401169155278397541026344577048268719885954430728566366393930754183529201734674480106203206463623290019363312979084715478650341161223807253919196, + "P": 141980468218021086729425270780989901628140983273843836197486412143086997665367417864947552967985064821254794961887823159884174866453944237520060398480071561024921603131139952545565508692859561717917207832737687954794504544145392174210819197123247752455249656881072756041380574615157389645625228714923098947043, + "Q": 159086360395186754268877522573545715225392672394752715251248772209546135935211034821472134760130766513974236955805689728306788391825769957471169797450123647530074704761819702129339299417113733803989411943993770864666691010188089582114353641232144795821146991778990702786354628101013485614878187725280871269839 + }, + "NTildei": 23002424993362949193922489560733649549293742111450016061470253657213366532315656988922193595049908631689658293221982596480539653128660476721863567039916060674578671086715450578260105742392333049607889275325047077587703440330421505211095693165846272888865798145628128465649532183743436430302219485879685130624377534828634068671164675137763004367669217185466171673640113869571972527485330323008221163922983114135944322467850308368705582418698378864361006819681804122336786280588837594494875823367083789184405372515571039201711855961493716324895541885555759790545252929102253821916608045825739345026901929385083535594393, + "H1i": 21699881294376417409800665900755924607855855670777164525594884747871505860436584048401458527747050348865319229176819458906139168817633549338892633494898000280183277926615153606045417569676555223325154156513009493610161569156730603347324993846368033127485038318080813554790829737853831194597788969560955827133083725940330105452966831624601025264661984171392078892063969537929869993505691548330647116399100307514309562475007699880846486521168316081337945887379661784674800974698998166735285948123919631081224076862803882235603448438227781785250678828068068286010852719455222477410149403637800669010058108608998760509841, + "H2i": 14045465267077099872848911353415869460863433388841510094438630043097727699472371984645771640838725208953279105395419953463936714832196310885825290292778240644741480849190631151381431722344402944704343992122840084706958985855854416991000494001595046219226524756249254341665749930035053446370727134654485029198655751976037954491329471913399382151757160183485581591945941068394957104130944489169806731760196225432711453978532711803596725683051547253607327263442398106379278332532575664251055206624365389525205405464672459419262955214202750727615105909474359838259477824679141121088845694285074318402013869822602311856944, + "Alpha": 11675540657945590192129941073339048241378590363276767570520214114566348422538514829738242913638679590191397265569339769088927479769545905112188297870604327382074002672236698621259598017032915881023798429380592706842356172025027077729741946405231021153009012573242689040139285597946178390548626707842840764396825987471499470108699995120839398156000836378553470490543813646043919287879264161165710821192676562307331611229329295883376839144635977577539685537413784509612415632436572771620638278172753665628651959175248526400959025717050822894538836537774249501781230276439177750280210212463847186198652099093621526877406, + "Beta": 4586120800853186526677836385883223336623024330838240864931296211140077356125798237713667607011239444972629512979380289719425546765687644803735392053569296270900309021095475571738392739573155762439416686764948032693013194392534740893484152534600725789078805222410450372239650368036702655641816170991658153151944222410554781900960506086405625498002302083973472533288569560489570208881024238253267695392717979255591369879269313072357797527920254860523598286812751168616936181113587040829015709126323807254608527484409930223214353755904928473090343134881462903919637510986747643094430419200360171462388544994312968509327, + "P": 84054578351311302693424781277032012766796151045755669347860286706120907662603036334258691508021966088443595489972120155733160179799613711215573783739843276774531366311112633664224050457596970151982039165307036996532541062372600039543522792973744702644070173557270463081815335868655733979792520599000295694833, + "Q": 68415145981765838377841119041728920965351900492940917619585204652477525948198719482760018128253579869523822218151702834709898616250728914275815156891060185646337070264796787511378036640900230906289072866422669050633322610645119524468329955569133346210085941508761202694781807583199414501699168601728561266089 + }, + { + "PaillierSK": { + "N": 27212596883874729434568103787891395381478147365555964570566206841558945686675846421124058146878764081423833120340079467810800620690713761225429305094560519125415535652661463212251326026123172801450581162532443375010949832780654738845546552675468799672281558484974557758304949102489626938897131098740019689892770833199110675892924255322140172713413629773221681617537623229137595146345681605621213155318346774180250586055795415408051832026457920062397228120003308532826276281308357610791940696946878292210798554400662640649265906699298842993166090457152155656789632117273046093736050232841021803777883453375835310239097, + "LambdaN": 13606298441937364717284051893945697690739073682777982285283103420779472843337923210562029073439382040711916560170039733905400310345356880612714652547280259562707767826330731606125663013061586400725290581266221687505474916390327369422773276337734399836140779242487278879152474551244813469448565549370009844946219931899672176678567231121692817432182312716704420985933242712879092222440360114777135639373883154632881486056421264755204699046545894984078289678406302465192942553588430089990031003328348965881573625272308707108352971851572780194352109607199613420889171578946106543311412681700659057080161870313837716065658, + "PhiN": 27212596883874729434568103787891395381478147365555964570566206841558945686675846421124058146878764081423833120340079467810800620690713761225429305094560519125415535652661463212251326026123172801450581162532443375010949832780654738845546552675468799672281558484974557758304949102489626938897131098740019689892439863799344353357134462243385634864364625433408841971866485425758184444880720229554271278747766309265762972112842529510409398093091789968156579356812604930385885107176860179980062006656697931763147250544617414216705943703145560388704219214399226841778343157892213086622825363401318114160323740627675432131316, + "P": 178622013594313389023433891200657260619505042945866893592157216921859560740498110958640140361466759744227435610021175753771006573002715642352365585561569346434092397692364550806272244576356743583421146963936310913608801352501268114566326511364302012655785247471299514462677351097661285401121944999276586678919, + "Q": 152347386172009146766359187553880588429499296866972752078980586457551140724463265108301736209113705170260178332931710143871427360363414451888283177629134256006298776439132880005606445713823616864230156892108915518951161643652014489895544731388626802355503711909533492650547518342042404216437767748883291428863 + }, + "NTildei": 23561405613286540476604998479716854527179404892055553049717276336050549550734409416544202858872947871609706451634586610948338357714659159664842878598185103678929685312631635729408045761031477244246801169705654624097019436744272981719474966776960406716411037340003812809221158989959243577094726518052002325065483901210261925552352912567176505395167039752184966824720938709307821133440761657324636233080659273277098052107427269314804719647583954645964283806179002905698757289115077568348723378241261798747302826980045702799222712109534396366956098040842968621488412132100558390125582914630733969666218511722499137537209, + "H1i": 3680022766237856340975109583052310004088768689292819583082711834702006001165457655359816576758322407117047903367886413696014846946406398650500577339159017938492252971760883032305446444993838916510939491049077309184298771278312824591873483572833092378426781224665298521197301921323197966195815453715701747212722938702547056145624876412993918327605891117696669421348064888468594696159156641991328243507402153365054631812412367374426377907384297883279465053629878843137391101205242763862108608578443260397959822833706377489317183260262318587101728111268738677113267120470863510392744903017792234289675437847142190245598, + "H2i": 3269897520867950453631263595456214449849552190870472450461713796865563422680415689759993271068767282605058900057847624979112184723345205011470466074671598109231653860765422924143365180433074694935343018449304811868958233435148044682952535488744900103931244618977151592995640182572357060509995241876883592293047449621571569517763051672472569015141471017539773479774584582259182420782135525445086449808095366829864338651394791374940924002392056516508219502729480023372749161035420221344509315532561563704224537757405358227147920079204117980106269411289320654914491765443804054234079970803905817624183838675214797298367, + "Alpha": 2917745175648920159073152880686927752187406960333005354692767224278728938734975379751512036788911495151791206604723276421819142078629586899802601887956552148964492395230004821589702001703987682262592155246560287104749299090273731043223312742739482613136489565955748931706122181587514463273647057505221644450665530326213552211251720784492914925347296415052540122504690052369640315882131272264395449805433224239894623305205754752437135049601832808396519231572974577234477380435001863657595201080978174463401289668674873069865321809398031092568530060084760814800049893560235314693644452866283976032193325470602861601553, + "Beta": 5232006984381929312264784870746527167456075954903984059528023986970906431896957468374908262197774562774670035940417206033395793606604355545891583896487215903925937413795417688634972641467976499684649584871172549583821282541242384771814928858548600862650188284641809958578336920423520986540603968559472812033634226260429611898466177229333321455024013772311674137236075621264427897609179645469322447176669881676339810916235703221149952222126599460103390672760193166188396032831930564578013179932369656600447259127995211264938777713923011724178767770857055131035363395510793687061749944802133155630462492381101132358313, + "P": 74934708086806890008131700647054424983585543887676780479609166066126441023833047480275546928755973068280164484665910023135992310492137412132301948511126434258536775917297865720363403978176559091412568041018539959665057225235240825539586574501200756046250265758123186876041155537500767785917045483139536065431, + "Q": 78606450251304824438050192256636162108650971613311862383522531824117739545996591669723210709150539191296668566091986620823673549756312585851727293683679703000318092219704254311993283030466733516696006621391164543951009462153354953436790423344390208926160440719434363706659111495509818196300416666027675831371 + }, + { + "PaillierSK": { + "N": 28246665701562306947955972214001672778817491919948552318723903271549355595609782350955414664253111821331386802312415557733387114327984317509274464360688005558855449343413371760962710900629733077881127193603290564608865626508409211100133158229459864243259147272818277327691430028622555933235596964285949156368162370208688293734224827524038275690085250259651612191608672251592291009963928565888298808568179984940193917923296196655955579228578434578310584876212982044643443451603009878799724039461504925293833108094898054137744978925189278706586664158876368398976731084963611245903204919243272837150546157234718929762509, + "LambdaN": 14123332850781153473977986107000836389408745959974276159361951635774677797804891175477707332126555910665693401156207778866693557163992158754637232180344002779427724671706685880481355450314866538940563596801645282304432813254204605550066579114729932121629573636409138663845715014311277966617798482142974578183912967933512356970153623262364704974882421017534514435790814771166979294743574806869463290600415393456281953414328787414784349473214459907220482754055901931909542918224709317587053194811051125584682290570360967775588614251671754424416993680297793178704054714117565339579514123861269822721994573832461000379358, + "PhiN": 28246665701562306947955972214001672778817491919948552318723903271549355595609782350955414664253111821331386802312415557733387114327984317509274464360688005558855449343413371760962710900629733077881127193603290564608865626508409211100133158229459864243259147272818277327691430028622555933235596964285949156367825935867024713940307246524729409949764842035069028871581629542333958589487149613738926581200830786912563906828657574829568698946428919814440965508111803863819085836449418635174106389622102251169364581140721935551177228503343508848833987360595586357408109428235130679159028247722539645443989147664922000758716, + "P": 175313004897583624770654108558009244961061558660290841981063381116459289330674437060656168641021515383957405497053702262092418083159000201288664248661647216052609219519755546139520372035676567774078215753295465054940883521950592610662854625365010310152970959512560632841573073574790288345056331552333532362087, + "Q": 161121336765996169146926890750856495359346665922292478045979328141873131146104515088716058726327682643672605597584919564294462198990514562580955119439530964771748395633835697486097277803726106350390311200880653531626866899895177247089822172915771731415650697215919933902603597945942903361500678017463396641707 + }, + "NTildei": 24455428190484615808370825213440551423980455562751150477446776498712840787993160762367843302805309837379891683124532741594302901438051817795256752775997988972581446321914362854151503792577618993191020796324855902478027116048353843732297817226180192000632671970246037527360804961881567479302832252185348739381459051802630563324121821817991224889087101889661953900214374135855410245698046800574083075532283114616498127816597564179155823680216938733427411686386448900024239920417466749642036400913337391437874401242767589142302736450143968773073556573561296426280856094390845646531530152018188464648918530500656448558453, + "H1i": 2057088929776996250098876489788450503037778688238076969000975437343285626031519342706114681993423880369912650779591138497866868500172220528253788254447333310546742247093403262999710002644705552186797302479000598190750997620622168886629423416538543154758497332155649470894461009962413509290077040497985575283629104045894202658798196672286998907041881451562246096561676930351374680248088561034234710829253605649331500229496972684007981875143981366797542286813082670823773200626725705975997438243143676944199756328042132000271152941416274565873588991910602770711303246665767366978419907847752501009801703544887330518673, + "H2i": 14955149280279485355327723243130920675191247906217604510150262732235485762376598307780088891512941979917507258601492629432982981126845154531437123997944273242043059092407643809659135918344154410457538465146295827446622810479929784603676676921306007398690568055440957573203138744398150997083377659994985465509160050621382309197553322422400412548698140902866529322437103587134498315712021069817932634367552431564485944327260352539707896567125313643152684979626998332365948235473522632460779195466019705000231242295621816908089362515522856041207340705305178270137502837138325155321140248840315936862316448405898759410199, + "Alpha": 1472341738726285674053363041243488547263891480532502535654696821601943643135015425439238145173206481485067838197278944256576781205047678452512516415556678553629767291252902850093558200467041305237300552042314305345324373185503055640161352398532298919288546908045846260622647510036782439975474035204590195708904324802546746399409777898802144014919323505165226774412007033398110170367492208517951509874386605878782868935823386607206768537633772792312894499450049680254212082669080962730054522850552173081160056851332588781016282624810744081230062874102565776199292457080666397355988504022263895208938675306003663663099, + "Beta": 3091756977564816015636059525046089013994155743954713708378071824763482303258500081289222459656729535414192395713288105459032267031370275005499884049502425118758424324844028993991773087512324294379012133748940359494497257805876041207781145910470972215843643089783898715263555434483491747717568971099888954323527191015639214047755035070770504060080843262280074392265902716288435471467038505376049806023351307582522384491339742382195133066920006045382560179989771519566051275293221388881172196855148990219145263120770315303437244469732090591982691862032247554610032904400979847571760779459321240297037032069580720350442, + "P": 82083611096124572982649810541028022577557202288925296507342766296310600134440215813921866305471999526214870838090350133242658107918488576484442287832548362991374109795394867789210732521412282324606273272591711312549519026296051799086511875190172719873306596941867964059056595211834666106731210320163886185643, + "Q": 74483285591096618913412451178553608486450949492707264176186074553993788579508683711426063313058961145304752779149245641200683614526655470943667795778596581140534555652452215245585480779710942611904688811215929423091269841831286615533531239067981873362530481353360988769814284637802931275533723327804533696009 + }, + { + "PaillierSK": { + "N": 25479243749626469880303962162837710303937541719028387823221262528949364439177460675501436499751390180000704377585232035693965743696644273794327015496396390717130191959414420378795621130624035443350184319933126832691470613952803722820316929286269793054394655733261854825338000882186756669372119473841188398981216078992641485543367075645363237572596115885243079497744457656153434117797053105475173292004913386181315470911629785267398368401433580316127205858718371565996226894714904800816890597989904276420295419728008542659245260905726160467065636086838524258566764859726041014762716301429109342392595289678572830907469, + "LambdaN": 12739621874813234940151981081418855151968770859514193911610631264474682219588730337750718249875695090000352188792616017846982871848322136897163507748198195358565095979707210189397810565312017721675092159966563416345735306976401861410158464643134896527197327866630927412669000441093378334686059736920594199490447832727814277216595232683937757152722633518597472153053042689222911331600617549530023971342203403448668405710080514861255334324792148142298716199732086337617095472679561347945752842769661206241927062604415151371314547354124638857760513248665202727776601741126747602584995889513779956893572580753175952793022, + "PhiN": 25479243749626469880303962162837710303937541719028387823221262528949364439177460675501436499751390180000704377585232035693965743696644273794327015496396390717130191959414420378795621130624035443350184319933126832691470613952803722820316929286269793054394655733261854825338000882186756669372119473841188398980895665455628554433190465367875514305445267037194944306106085378445822663201235099060047942684406806897336811420161029722510668649584296284597432399464172675234190945359122695891505685539322412483854125208830302742629094708249277715521026497330405455553203482253495205169991779027559913787145161506351905586044, + "P": 173880280332539123970960693466828164625892457202723984619410309088532664610696118303603857908223491139749699615192245586511461319317545335288384072362013893057900469975944888816578354115040056521359610594946689338050012337410970633393426123208264778486217193864507237451218368679369414804137859122405130152183, + "Q": 146533256680391986205649584020895102524956390845411207018961968619078789985121888111521491412283088144228959876276509958376238432531738696241389386892184997704135479379837216108806558335541807415081683924231550578566153860065912118151183466299854024527344183608038572141506153722180013801312269049815795169243 + }, + "NTildei": 26393211866117610599753747728775425255461566210652178559505864044051153079520643670787521555812009867195455990272556744881520564400197711841351059462452719308362206305144283427594953287915821638203348587580342287988782561845411091498804613323392976818440385552880405167164975555592843305692744598217780798236585799903030965217685488172780248448800495534478497244966900068028803427997449791628872739599646894897846561306065904503367222347350262880152926785840265757414051460734765737587172383089279537433037409334726391349437001504378838298933556069099211235890614864857967040355422106968633278558432654391495841145497, + "H1i": 7371327340434187711375426891572483758173950399162894114953811894632752168342570179558425317700869024370224195076967941830056810928888546039656050315068548928874030710004062004983225275858883022406553279041730700708428436820530227449519665350573217827288178221432840694897044527459923130511125087937996787887133979848380440821657189519736081580112799350172917833619188245598967838176116052540496813253254549702854437838396259961048648046515421577721542023970129496253142468933916301556135307316249076081846054295515284313633081208151354020187486499183606777660770552065459456769098298716541633042864480531904742847729, + "H2i": 23408883372817245431623821039748529464984527453480266166205919826904647746343226021740845608762592121575756044638369259413208891070461705476949924798223238057318087838184778094106157350552596110169626035988391683114841768799301758526035611704996400436118893721194878906463787076286400797103582182066604317012892105300199682020894457762982987965093791862522375759834800827184017709394069639117083090241717897108726838579016816878528299567515091051723989531665945622577591218494759959682955448428323211299676270038764002300699888329429244638339760607070589670154087659251513412707998933888700819486469478901912226889917, + "Alpha": 1528395940989684048015606209941777606039875574018981919592371235932931785122467103945339243480854798750963882320708985426604891556770245458306396052798181649165979434593306550230643356388436183574969889929903164750884784108675078342462310074862665006720383167388116393013804473809687986888586072918134402740825587926529610482111478280521927665543149181349548366916363242880538669473536341437052887674207205258510446651873695551073980627680479998706518705517590148033611800409208741711667913538037149930564050925952095500616035091819004046937962122055489794034756407915178880859265882889809716513657161984627447031116, + "Beta": 797707395386479786526325845211584604236092110930797646485236511963945246019295642777459161402469302485638646347207848673162277867789248043335199044820455980285410110627439613987201482178158329910763268801278321002047058506857802354225565174043700323450942256465029605112460233703680611658821091995455247823998934746536033588888421158539414385200668283475000081881132801045503778833550980873242289026436872491897383835146685435877788114324444001144223621776940876566654099531851906036993489200946446443842623346307549331473973074198775196464802975747474250313863873443102538832860187816904034667478927615652898747215, + "P": 79657221346437685022787088408951447504148494431944620730288688592082568177394726488665307453838354488567635705737888977500810551927416534248959278698336018184295851326056669019390599630807847508489118683427018922514923983040555677747981022193931345026121380822450554097974125910468846563442442294512746154261, + "Q": 82833707415335074407314325478498388590727708217946677571559792243039843306003884302544335031456320810546703359295509981295230385226699056636545991505224286130453588674665414955301118361206386463884385904268088780407867937755453681183422255872195951793246122283743196339631521262872267779805363250298497144869 + }, + { + "PaillierSK": { + "N": 25252589818444451042874575455049447519278140069243037387677852557776155581036454973988879751297357336405166760276018499926235092787916495952378434506548436481288800395602670576493553119453407929865738270428229477528236953547298028772017052351368830425964871933335601787396686589854674799895953157191915465557578338757388940291974111656244957932016659424705780574849385672801575510229682264178882774469164725291154623296955135215895102210119878027158165685196263808438763697563357758757933078273361894459359896237005468662383867261829444259106293759461577134197117373868064848476506282685146086302833260104799689748661, + "LambdaN": 12626294909222225521437287727524723759639070034621518693838926278888077790518227486994439875648678668202583380138009249963117546393958247976189217253274218240644400197801335288246776559726703964932869135214114738764118476773649014386008526175684415212982435966667800893698343294927337399947976578595957732778629940777714003734332254217259955070833612968894900846252127005836872862855508788916671854856484305748063688834146514993765269009320155031554860755929270408023477382134734133619515779031348022836655519277770819599239464969638073810365713216651655048008768898807327734649684325867590008145618758077496595985126, + "PhiN": 25252589818444451042874575455049447519278140069243037387677852557776155581036454973988879751297357336405166760276018499926235092787916495952378434506548436481288800395602670576493553119453407929865738270428229477528236953547298028772017052351368830425964871933335601787396686589854674799895953157191915465557259881555428007468664508434519910141667225937789801692504254011673745725711017577833343709712968611496127377668293029987530538018640310063109721511858540816046954764269468267239031558062696045673311038555541639198478929939276147620731426433303310096017537797614655469299368651735180016291237516154993191970252, + "P": 169286312039755103910929642853129564327456797629864262245180686782684274478200105078798677564683342993774837870404737823802248850113540021201687179076422344266367223478013815593031548264232872341164848359956901370091881581913820490893091743832171299815285139001003879405798709161493312811362322456176564844263, + "Q": 149170889921177719398673578871918226021976689286114620099950974345145510040464581266740387191512770801252407758257367404562315341366027942846756994261300648125441709815875675925869971946432976444884009321506928093813055740639476147481775582326095738364294437252405499771338921788472757200233421493629932934147 + }, + "NTildei": 27427949615470901631400987208767075324259173811619071604281178795965441684595714230361253731752599571033116861804651874076807625414175718334037017541303491611565195594055360133291209358488065000478871183667646104834575239418270508555406940396413090565218860493732781246178188853088803947949185051580711421997603403771915372372941760511292326611244204234537710870598336539377716423026031253915544611200546942265406072311351849575251365150129536095302042977526060410702932875750239738236656240320040066347604470654327857775150476802880365121695560100421410988240942887845816535778258824341115007613038602995648085094961, + "H1i": 23812814745454264813635361115402202228040566149273261312371779874909366954182190589803623422699328381728167192296252747988409671331446368050378560933618922167863613591615054492567069723567794709590689557049867910205993321974489984469957935400531674113401893456623967346272090958581351519762323277589449490680990380117519476382287715007860938182388640933105458732155442043054653789880844921644184794938360607898101345841526480504977897720108416911032567881673084269631157208363858816555494386089982977600766660734229004691967383343069572476709107270996257358909609200053233619331304782038100517403432765681956263886393, + "H2i": 10610017033500179156909701073229414381487012876312540252355179159713631555568117664635061976226421190480292931215787669430768659803642960289527882201280049467990618295300728852164658316721753428066589551437386120815129086041984793265894581456712260954907812288081395577779293589801097796635570253074540245416644185309398175850817603404201280726921490752669079118974817919949545183043859926014637453835738239560950883352945056848095728299168850348976918503174825406429941473994819618078410365910701442577753546434727675204323169361789917359185831859962065632928549993484722339698083173215397920643234312073778202540208, + "Alpha": 6068115454397878946500188671053184170561770081170879690352812342885863933217220195233805231066301121925608356275165315579919344934622587847529530791307716500752491745048590813884593227379705356629048724402238621567551413606483500103923814210758471667129262643157391949915361243700775663301135951701055618825853790573749640502160621479113227640739376214481152434165136254078483734017052986617097285598183279750658283316116196443635528930890348204124349836882082795547712456819373753897911574531153486028869742067148957922545654595537393155233588421750096967560429288289479157360637252551087532376488890244181344284730, + "Beta": 6558270197509051242355826865088321698822154254758404744415769548282781995645118299731440407366561165040902685274031135649550443255545587650304986855842229616970774166127479746090703636092867500591479343309064149375509484386154321834207587469619642299277656618536010247084389419508196391967534914728341485278111726776132172545046816287545687477947244768311593855104851443900122453083668695056126680931440065320175671289312035182740753269034388913373745339609637131817932420197897571131176954144533298095741660142426773486811058026257591560291023319872300404742119687808375376681821554503761714668499187363968750252419, + "P": 88594306578076746831430526542997088951599817936223356660689361417437430113519528828216255660177992698173250346170112414321011668306115015023168803845626120504285335226624023098185919554720261503739950027002937118732546162249714772379299288312011834681643103641863335122302432559492119722757352528346735173893, + "Q": 77397607913153786800697115122332341790726923909878450867868503237218148823466099959670290371236847346581396730911494613079769097549118191239972670109013980353995989907791303339929080371543691079798846810231457296544247623638866049187036310405194238890888306026406427215003545476629243298914044852412739653401 + }, + { + "PaillierSK": { + "N": 20789640499942298282823351484191314766096554305460362907973136892553291504062726704524368751297046204283013517317380196230534747422116172322678957282950409332529768725499971972515080055484260166378082341783116741924883540529624474685920251986040557837278896518281874278179380138547452808150262593041398913269140390676996278764661044288800948460136378202462438604208352902115149069653381610853281870718860057534879862280740240711466876067629607925738866435302431673185628348035093030131337482357933893240490368949003024829215510185252901539097416387084578520221336916554743577117834908070622142419122265336473515947157, + "LambdaN": 10394820249971149141411675742095657383048277152730181453986568446276645752031363352262184375648523102141506758658690098115267373711058086161339478641475204666264884362749985986257540027742130083189041170891558370962441770264812237342960125993020278918639448259140937139089690069273726404075131296520699456634425754333330618610372455099160247396477857529520193623218572133713734903659920301873421112883370798413965205680379312255025234655272868111672329207892141265073347535277633039835125570005930098418811020858493137463533442355734213534524226702578770471309178299093560003759432860790299321518034046364758528514598, + "PhiN": 20789640499942298282823351484191314766096554305460362907973136892553291504062726704524368751297046204283013517317380196230534747422116172322678957282950409332529768725499971972515080055484260166378082341783116741924883540529624474685920251986040557837278896518281874278179380138547452808150262593041398913268851508666661237220744910198320494792955715059040387246437144267427469807319840603746842225766741596827930411360758624510050469310545736223344658415784282530146695070555266079670251140011860196837622041716986274927066884711468427069048453405157540942618356598187120007518865721580598643036068092729517057029196, + "P": 135864089995883357119602450187001896770539697930802077461948643311505839299049816349709622437870878288927932337516872113161707839501741670803049172230932313957191922052710381961884830385328854878637504840666127368447288936797427472026835929242383512194377084956830093972804489073838931190636712102680875078679, + "Q": 153017920339158186796531640293451770410123445491249280309259991376173423034491190756730022514247582418021518582464744088254698917582130031591158847287216829081741355427116568499201511960744841524230822391350622533701336536987046998022127052684654065408603233410793475626164697416184568192417460504275583839283 + }, + "NTildei": 27383770483317027957544429693805573196572439549819437357507509369021097516488665385168493459536004159792286650289099441312297643630074480980368205403549136873288008058123813043145655145730583472331640725287658154064706738976226764544453413827365410082859013030604969547458370262271167344046620840914474765655776425025544371231547791153602456735312874616264767772741174196913907322184414646326109683309038148872550285383028856028873512050350235429129021420121950666373968531365856539646264174753341847409019435612727868705162170200344617293526694266822600254062481438876772460223606571540844131616873191255835320796961, + "H1i": 5870122117057908933416424711289193004009190105370048825714984621687152560716332898477220730836088586756915400023045618252055822337706817159535091668041743956324118324477556241823782255444631130755934913799229374182784505443208818305378252084954433238605495314428702132475611387388629679317219877545962989792675430137245076827170325335772789889196461076205055346926249849559906833838480966553585295226099938312009716350737862011307808765143716122764268128292492269749603922936139286734711644256536679883174894111207308418397954528394060197087429944501689764320445866630249612465757075293065389131284232395157260247601, + "H2i": 19367217373650583623355199595666870337928209385852582926649720420103734510104200499573575057213009158923275334978302225563068792343920096051084772113486915693321510879966874835141400609617511212772108749097427999386359743305718288912133208156105221889251886285684297513196797224348010520152528655662910900414361536288689655272859454845352431975773658425772508978513272673121457894485494379191587613445575335076547253722487675021029339236177080471926357213264339172623729843964670601607240117012053222388892556253742950090684684439218889352577746078690140252785268305282016351300553932145046362324347061405808506639132, + "Alpha": 24463260184082860254587319994513308777916991116866545612700219230526339667587178297539388637479992140514835776412230552954097304076419923911529451704823351694180633479027384958081029795210506383944915850144646263117289922333508541752465460090174210769291936334505582484180064673264466507694032455009245002516608971999724959282555560991595410651702500881051810427903705028569160244719372262673509157502820998018848617116127233503846236686911585566817944331625835737420097549659515557998568159304210128544826999647917179404482085910432794934910287092352665521356390726220414954253614774629679845106622141820237657346778, + "Beta": 2774378631950531070764487216323628116269698318781503259888730819843320597730655156036340181861895056467054877709885766811273853270187819356618912306347297385954139747338713542148524878182639921954337756868453104713686210498455349862820405729108623421661749256949559079279141302304657465209699231356003565953044754471106959867044812204792741558532205029650340115133543145446691997845005004923711813409753608960299539146041394246481299325528303237165857825003331010591005560904546547530227667324988111601125634837963062373318087921678278803669458390818639753049172632768826133593224486040662763347621295032286280893358, + "P": 84705375750943317829167000294395499027853486772453947320027042645329172761372880749980896812747623763096156680519968497986613241677793043544254556739202802160982180780446397969176856947632627646778825053613525859465650049301048229135669576304040286278241592311820435408862171008886759392694684798531748605071, + "Q": 80820639305800109615407389611676731354764332460804712558700191561055131611113343659173714248021775382551239207824869971781141263855314425358132372745331069701889754177854147705858432437235283884301409424983576099901961256135630165986408078060982090785330806464901802021146315630209290559673832709301056080863 + }, + { + "PaillierSK": { + "N": 22452818887673591415844066529698274193613692714074160848471173379475539476659377479751485760447401739718781153188204563440616148090155544662389118761192768786809694997633466718141961322249596856272483903415507847944823524321013255203492926767612064412074321036020904943588704780176307083396436766758824850946934208863185603183797008530608840735119015592816924356787336123048362371934131867165415640586223759698139986828113285662382802857339350033062991722668855841462255218546136723663863828976710000070573793365770666862090904271510537580715707044535625983528255325831444205746741658827750520434158542828067740402521, + "LambdaN": 11226409443836795707922033264849137096806846357037080424235586689737769738329688739875742880223700869859390576594102281720308074045077772331194559380596384393404847498816733359070980661124798428136241951707753923972411762160506627601746463383806032206037160518010452471794352390088153541698218383379412425473316947293298420438369472352575835878476679047850988804109826607480812518109262061771975063487802174839472518103024442388315831697572842901080677033904858644122132935898318896051001361233419035732546988089576299788161799235880659388188370980971857069488180166365039898206097274137153616334051560855302436452186, + "PhiN": 22452818887673591415844066529698274193613692714074160848471173379475539476659377479751485760447401739718781153188204563440616148090155544662389118761192768786809694997633466718141961322249596856272483903415507847944823524321013255203492926767612064412074321036020904943588704780176307083396436766758824850946633894586596840876738944705151671756953358095701977608219653214961625036218524123543950126975604349678945036206048884776631663395145685802161354067809717288244265871796637792102002722466838071465093976179152599576323598471761318776376741961943714138976360332730079796412194548274307232668103121710604872904372, + "P": 159870391770138679590951501912924801709432928181704706416260690211286455991345529765734711373819683225187025512998188016932207274434189910528559889631741437963377649318177650275612275557693480437379586310127286656631145563998513779696853028437756241868235916248369543669439359809284808075955214411143245481727, + "Q": 140443884818623627467112323544244176456224568933242042151422217875450879724262213855730802236799726794007925109066212868818932187759474320373077765227397115254611697431321281286248830952178448168100230876490780629136160235750705024642112054154155602683659076852994865665107750744158479690100206706319622016423 + }, + "NTildei": 26721269687059982619263305691645836651272182163634293798608244332260479328530818177743994672658433328797530323564529244462395937067447880750685056093140513104243452918122522142107097576190561201170781730336794665542858740868165021207840027800504669995850368201896386081290325225710692542129643836704094990044956777168433984777317740941014324614328237760771796230172105749127935855185188630453341760096632169969430174871994793279861890981835125770645823721458758675348165600314313187070405654462012157912741314098970289822633224338176322421119790564763519684927002003128097211012640096157497123647488069731983035323381, + "H1i": 15921481532188214246189063681719761773498423722223607429579639620519021937215811463713384371306447774918655813175361686655015539508271755044748379997372362875038261274076259825976912663972420333452511995021871532431540143400063621154399538451589747522242780356852253035654112806184272773758149081272448269820457091153344916140785392340275435146495907028857019310316922822891019170990110350518076108986863791024003725020825455320933385149474295486597735154819630070696909420554298772084399999486007903483361054159978945904521435261125987294124403087997788904786552206667557219689435664524586169734032304675624533554909, + "H2i": 22120415505787583100414221311871234924838436080303172132326115810190601110545184348151888600565570789852914511428014218699048551003007308883950729513271287958881143859782984233996178019353526662797569296896168086740728971775907087192500654569250325855299576770701120855355739560656795077620926026101416815721341054634507925839238504242343083863765906102579833528994626313229865302697474896420336039301937837401275492812695209457320977879743127805128817350821268286179543427035513512243879429630623695312927501414887640529843654490047238822036998852659376189087292770826292863156998524687055024411536866136880356767404, + "Alpha": 4046794565045221595160211067657300747068481817185809382644642570700398634901779522698402606797728500843527688051764149262928543577891552960492069265026104230120321289494744698062421892284691761643189185665596592879681559164002257229279074949521070458506358067539376239447121967839466922736795882511210465810797212849729736981620846926513878495652895060298748099516240408411881708253822245054357787372214782428437413935532338837234420516596149018474199914858387864371948443476677008550047594522631430760772617341887133843440248857056402802710206224614446210363870787585619026326232917370899781727598515889704494958728, + "Beta": 998515606112900320368973522517486455994006211341658531315344410033333341886327328420214997836134664837043716186677516012421311688093197585496278741600850315434332691104464330390866065306665826214105385712573318465788805373819442731002722574038533329058686974915821884066872840417265503377220840450898870198810873993918042814031256132695745938523513283002986060394740109200165294281838618750967597804208790863090341773689775832288650595486098953673796369896198284498558730857305664117171797769338610485926246295238999650332554642709846630546943172186060815480735674721574223678068632042334121237077755469480576513291, + "P": 86438935223080254461231834949819663190889485406785969394472905849809326153655072734241331847186424955996708200340903419815538564241711576233452293817525440198815228076786103003417504157537212497814292181309998352530134388474643358087763904918093081297194888791057402686667501872636704502740887945190514744129, + "Q": 77283661633782701647768349893835501718145616449137563271558330734783424149064784883372376067698259075798939980223753255266432453157027558003380650196732559201489926878554650084676126297113849694791308278225133643216585878548214798237902131555291993393941066914270122921430084293641938889385203434082989768979 + }, + { + "PaillierSK": { + "N": 24584382908480975648950768149379041346347033237675911038758584230080410652227656157991136307550002528100442183781829289795947747099757937722295545032622860443292139308252031978958388592766335342408515928320254955544468746408413500437986007203137659374061846683321952311722494263061155311628002483601515451410342819605990734756463117392496537917431190419684017852311540722979897991431897270146348940033322842196904263085593020935717638947312564483576306320463960720088884610675535838708887447460471119870753982784418653199400290117813775438891101133626589213967200750299433180884572782958371221638230630488551868704877, + "LambdaN": 12292191454240487824475384074689520673173516618837955519379292115040205326113828078995568153775001264050221091890914644897973873549878968861147772516311430221646069654126015989479194296383167671204257964160127477772234373204206750218993003601568829687030923341660976155861247131530577655814001241800757725705014501967509011726164773121187801171119440006279950867227366676303140559044885601964869680060853290550989761173785590974159268568457922657007584723545531789389680927189585607485007784138831851248252458543661823250630910138620681381584523485359688663097132676551584304151344450347592341685202702278730527658238, + "PhiN": 24584382908480975648950768149379041346347033237675911038758584230080410652227656157991136307550002528100442183781829289795947747099757937722295545032622860443292139308252031978958388592766335342408515928320254955544468746408413500437986007203137659374061846683321952311722494263061155311628002483601515451410029003935018023452329546242375602342238880012559901734454733352606281118089771203929739360121706581101979522347571181948318537136915845314015169447091063578779361854379171214970015568277663702496504917087323646501261820277241362763169046970719377326194265353103168608302688900695184683370405404557461055316476, + "P": 162881605529826893621658234163768404895732946798002171485839351414792154677341965400143391042287149958157228281641680806903206734653527622549669771979258012555980424786751987531850581034586312043853606316886740368937897517844891534394023468161005715881558306550380071199615935448237684412853236561647765002983, + "Q": 150934065442884410511912915957167170296577460326113946370968018958824718664784100816466188869329111136767512456380158180495895075743191547011467101393639128753542331509612636207021298148221105330395459380208266329200572322727521141328030694746206171891377090645884501382267946814948853854971989369443048385419 + }, + "NTildei": 22239087147767966050699589116041431955280653644672850099055689541691188465736454521258527692669672894323728650758836626393310718162312396489457423261697556645924038351263137555752777948473068824708730731323323800449751020800031320602068024435028601498796468713911194053070463374097864933055215266307400137058959601582043270934384187333373894930895829569538972533233676194246108490903095108579653067104015690418699912236314919343217617008345840256190492995260216954011115345846008288106555697444897871868456547415737232288528456054026636985518792071282450649226874625922495796932551331326831219153298751030102192568397, + "H1i": 13297114265082019793261587361825196699128448520129813679345313801765729953078230242120463541397316436177333279264514926130539589658398011035796262799974728764262331313035192552415447586545393169929710486487146651473043980511777242897799637882464522993480483761323963100042615900197153788543524746187822412625452328161193061590439014570190106682977219564994199860754181519670974889730361096503164891326953462146338086339029470041877961171034768476322729120883492543930411585415881278843047659867164706511949307283676643696302319545570562109793049723320589627626853900539170043707223809262033574742698460043458838649426, + "H2i": 3654183955562437129402143109282543443638072794674639476213599180401299693584131386018263855489609092116479987247495370441323539601552512423556880653995134967145628986385695924455845525363889174573893398867404947657327357658098991011122622451120065504901559511809785788270778894085088011071947083294015402175789988770237835214278915800755266734726076236649591049242375350063264336658041350004572716412279621503150065399450803736791449418093102821111278412053257812297218244213590612960748124102587067026044684827522011973680152208325744511825710747499216101318985398360977601219147531267687832542218487683744511634281, + "Alpha": 10118087064614406614212679940429271500859025907160293452217731542829040353409262644125021064452783685825208017997202849302484923922880334507510360432569705086478462815812400781952100181143927151508000887982031952335637980725312490850130730124860801781172028801155823715788161732681250899173268372535923827587187850999313697451235734705200601101198957700616602862100960919397857021651101086261212763050534157415434566285431025684241260239329229522783975903305701469186006697684422141728894564144300502466476821003823790318470736493523281544414637617666110707790816929388202000209134510867045060275602224932162576017720, + "Beta": 778000338768556278990593993918718971311826203540745019591493481325571340595560077978076224860992497205312860455356380325269746458178715563547298817247298973522967256243071754848756345366620964779839317678600258393151905842936138269522704039580561348617635701060521254167347018741955722241724875978792777144060509094183349312708014479697061225922651065670797131345735061618503122940913579575746674950841607069255701321852053533153495491542263122143661508119600057353161021400370905218122412914976434985620328261298896469955165596768869916631994577404102744880436108848556890992093812806812292982615934668005894686861, + "P": 68240525539265748317609076099740898917154380874011644884016926975733749952333189503283826761447920761152053573150839155522906912799131463984738586970770718713881256096639041863378262363329421001737374302581979601376202390161567106841790696528447370526701414047977216577094845859190882370723540115470034281891, + "Q": 81473167784191325018775020719628860678926559752873569259721063253720716736039982722971455550952200374923355780638334908894778798278515123977507809268971930287054823553585741889342054957373657057534809163559496008873338693690683795887141374662781125522949562356022006062230100579657810419679685605146688512229 + }, + { + "PaillierSK": { + "N": 22605584510643819852971604668595277832111790967967245452622811607814874311878641646435377790111674054998839491510576161547517892258197782780740839479700966875123827589727367273232713501045670069520587190172852803051326535228934021631018199856916872988543702014206381912395731015258334220165830445967051601848136557344699445375146811174217565070037237389374422142923402991326075601107512858936619051580699414344536992569678393864388278371052171728212346129858415323253048875402370832935597623682497329324963660047695353893414384449363058933019953393590706722308709744286083489989752845968381287016945639602520361454761, + "LambdaN": 11302792255321909926485802334297638916055895483983622726311405803907437155939320823217688895055837027499419745755288080773758946129098891390370419739850483437561913794863683636616356750522835034760293595086426401525663267614467010815509099928458436494271851007103190956197865507629167110082915222983525800923917206998115756717907400118918411474188090911674401591151298655340943715246732383233429990909851462548275155048759308451222921566949459639544523173824991634669819780338175134911985670018848798478559526766297477337933693636553567517594133253450435618923959535579750424679511374214194224406749988206593596309866, + "PhiN": 22605584510643819852971604668595277832111790967967245452622811607814874311878641646435377790111674054998839491510576161547517892258197782780740839479700966875123827589727367273232713501045670069520587190172852803051326535228934021631018199856916872988543702014206381912395731015258334220165830445967051601847834413996231513435814800237836822948376181823348803182302597310681887430493464766466859981819702925096550310097518616902445843133898919279089046347649983269339639560676350269823971340037697596957119053532594954675867387273107135035188266506900871237847919071159500849359022748428388448813499976413187192619732, + "P": 136338506033958287858578462113872137930469404074040812026011016972405740973092004145551756581163890460833450131086760877267498346781850253036878099376694308854343899962636695804944438644919566646139270202781775553651404922384939487637249394638033544525717886385385780695676984808348213131727417082840562524423, + "Q": 165804842433973651473432474266869983730586161951578148594794663671782429640956088324207313179832598787153232341073016084674936890371402196086421682831737745059065414763383867306681844999880165721705336312318623663895592253870984410194437492051801939935072786741196859935053112731644625071718246106492606310607 + }, + "NTildei": 24120622398157980596958920318728877494533028551150162111301680937400307909155373319207396398123543078505347893991079955176367689875915070210229447682262846507410968532716761656551545745840716239937036199193287806688693658899834162351813747761658885772979707997500709468495536232421528988045303569234920694924604596447741879093666520593639835528925008579733669507956403455954878534887822602453148273949029534061121433096499463691710883340000982577970540106028123615815077512503558200598077160339936356770797492336137599231646017011532226515194028997932473202811004145217663979247862125983176865984280298309953100043673, + "H1i": 18977219613120076128916593984852791179219907276548246096260469902584307933067498516740405172890306683937710129019634306097386939109184953729602461136874883011546212304730033046200170822516554967799879454573371563695510823464401764512228392518185896722701011255598394649245046198209539497127222941366084493730770883592511668925476233369973798834465023815926826481155709918007130476310238624938533484334295872943437209846627250638794073764166226854132512065747336422854429222291918188963946367003132467251507066195818360616075639046082603340605897465295704586934207088761390924473739686667262940994981221850789868592535, + "H2i": 18022927234925965267245078806516216721692469966403481709632621984248647860277712747632846962218538874163779731658181813241755594412267194294432612692312663244136308141566500041174089392700232020332767256578544787936732573293148151765379653778256558203147920811037486757748124976398714215225316950448024033354820246294306224868356474020247458765812576526616195766128077826952857354516175524023208956223932191749687374152958320070762804720526851582440892149323581758209056571192890273698165358058263447636324848165997064032045555234546782419781702841499221198083492008045860824389390765418480117940541868854377524794121, + "Alpha": 13429315072264996346484003951603612009670374743004456239896881496649991485006083133053267099296832041868659232050938083621021432605283411821899203549114688654282419535756586380381135043568278245442187653505338899399104282687239638128548160145017571119757036658682156396289770456721557582169335499726757658945985537595340154886393051651633894536467516640351143490032161308174482530604997871016519386227080029697172071237421584393165036472501130972162011188278910247960703899199874849539881916319358293048544262894399481381460612630680045052594642481485524472748006840432260902006240908993877962047953254379128024007089, + "Beta": 2978558682769694186109119794848672295825936301811076729581714961902508724568275346435321830192646894225394397432404042073611276719398287320200558428250986906205136983248355680221319451977952019771396698751222559126770049099992052858226673035463289365948412453176467400834728866787633316183288460010779343009693479323438733142592451879365395428172440382922104960817135091745073946259509275434653118435620313463040838794323391702885266047373149475968380708991429244602873915491996473259787266034368302496075278685362083059731555394334054432166579542206552824314719331915178594755396689632089718542063457799924229228495, + "P": 72042761095723851257253791541791348481905297407538949969343684113914809126878570938145121811850400481552319822612064342684931325009460435748586415401638034451837543701396889826664928100121273742973467228680539386201617465102070039490650931382768928606612382092073550411785846595678164616207367963510246671449, + "Q": 83702449875944847358738019979177126784917981002853998939238296358561334863468409270359739197644602688262618846006806144814769625740019511351181136815532577823822700693625170070460887157655940060633469253550905567196508009943209673320500631168979920551959334446632623145890080522242831158774196818482496277313 + }, + { + "PaillierSK": { + "N": 24740692502624148665741448924259677384674506215958266677587350648073289748515208909009326802475640446771166282904712813665456754146469422056929065340797679649080825246052289427872204122744058115682803292485153936437103418606782303678419573876662199949507500531367627088352628865895730977289279658158516302712501274044805028857652673141368359274378349886731940457118730045941218847530030518688926705165955648772642590439456879121175920942922844595863429440120380584527065774044105321312956386583581786961628328150459591863581609242573071054524673086989903297085580967170736236219344467936959549900186833486622802733757, + "LambdaN": 12370346251312074332870724462129838692337253107979133338793675324036644874257604454504663401237820223385583141452356406832728377073234711028464532670398839824540412623026144713936102061372029057841401646242576968218551709303391151839209786938331099974753750265683813544176314432947865488644639829079258151356093155973186736378836823892994648654702756095122296444904179894478996022604016938734412666512136740951841349990903322967974684213885102775043333939148811159180560327119677151647322558852078536178214281918350852276078909991498213056983079195158332168527157973870042175902468769131556166850841721990671802262958, + "PhiN": 24740692502624148665741448924259677384674506215958266677587350648073289748515208909009326802475640446771166282904712813665456754146469422056929065340797679649080825246052289427872204122744058115682803292485153936437103418606782303678419573876662199949507500531367627088352628865895730977289279658158516302712186311946373472757673647785989297309405512190244592889808359788957992045208033877468825333024273481903682699981806645935949368427770205550086667878297622318361120654239354303294645117704157072356428563836701704552157819982996426113966158390316664337054315947740084351804937538263112333701683443981343604525916, + "P": 165200398895521785232793120977072857777071962239124079842686368616917226294235774571285458374164442123983736162748139751691380186294989135204501838998801725846011445785066885267463834972903939558213892664931592061551337209188713375629370186611449768973838673413716422330841569115757220837626968544005341181399, + "Q": 149761699536034314746232234401989107195765734248223487467683888366309576027760866648815913767517724744976154294902093433535172328857649910572259722823956540319933674019684132750847433906520775046985871648826295249872452050387931564929144510061789191057426346016935462083565360558089995360876420961273857026443 + }, + "NTildei": 24199931611159732667054901284490432730655788184281673432799593709944600778671364440593923502464750662133283104089850262827029391732187102003108922690506359692667363858878257472490872534272272418259557695490451365566242979496100656724082731811492965573734883806205370491944735968733787315910956955790939556490084165533762006153993369100619396765552088389603636837696742761018700152717925780757548270666166602686810410134455710496216314201100728243709619700979200179375307395338108536012376112172325489862898013926599264560178115009784369239921317480668598756464646766780271050093100639911257785875700458882588757074601, + "H1i": 2068908653463431643806154458199836494675279526119505579449082881064318339507925410665258878193990680580834374535172214976293092618598274161698908097233793492032617772901348137115521118626117971398404886065705663428256281099212947150294401133914965336879981232143825731514235533669488348399079887191364690761078227537881142873162282969110468509667384289619398927299555071835201951023264644366925150859414451218111456692619537757234109465096900027933240786155087591198001276894796561915984092904098062463188145478905052128009943736847997316976312160672286441346086408247715696381189407852858236762374699467116123052327, + "H2i": 20558959829980446976202231116547294366418136649478025735535722578937983335779516069033262893969183870726526076163028164887486281219932832748608769086153336173364540278456142481599658371726284893455190806154272267829477900797754453341403052297963570155859003155230054211243958571590924204763633513571900209861190366240928367228429499548907518719965162692887786229471284227539280348373812393889569464962675302670353560244909328999065595811981269667775787142090179012470330906457454750560182534229196410872086219202048994553726767171353751458704492112821449702111607080379541227334079368156062626171348563056919382991456, + "Alpha": 6068636318208115996729122522066379531202759984313360577568127970474383605397302207042378869313558626773325833282575305200590872373097797664216264327353283900990778547737467664419769013719914237220223361165705830817728955246483878598861065753429326718746278904781494106870070010649161830080016202253750128587485513364993551994547997260809612224637139160358464217226754938125016862778042592155606576425740470291205147734610897437016278706650151722716436878422025549721753112170731931141283828767269351653747840060406967326842737141730563515843023981703230127786921891986332025454077416872744360334736762935983847717275, + "Beta": 3750060602396386393824697879759054275258507317125708254342493351741777400179319079903123788930251738927541271990566462008520369282855502686589669565969642449479252167781427444479384429499855569180925932900131919419730507582705860657733681357982441119692499478575307583826514516615738623202808700120938844677130900282392631668812180966604069646147093547416098214528706324440401928864483960795715288389221789532985052117038731157438141347706245101912661444531663397383665729901522479870257784199405846521570253664338996302873836871117941715270109729800201738990462975260341324743946066257113201700627903502279912716203, + "P": 76393700366050162749373956053312258164376584618272795154338189769192962795021098295179894864816079711762123968857344569689990633157165734183513288567169395573605346909887443769212184857480074412764005027500436205394584198654022100650859433265144371084909451596149491803281197090674495540438670467406842517009, + "Q": 79194787970744552772944875788559481013617629713879624724647179118324187085055559157121044610209366691184710406343411127750302690296611752958159634028378001589791460329229536615833204181700492027215099448133795803572553395382536383051297304355497107393780339516746104919343858629954144229557149068277233915489 + }, + { + "PaillierSK": { + "N": 23565974365787109829436420653002558338612751978005946250683009287762941698824452350842925783048480706135043398451467385607982064790978394019948336958202813310194299645119855728689109592187065223147698672553785671551921160642994009798684441597915227603907697136142125658636613671423255134448634074246978450235494513529373997673587714923952468519390145698734622905672454274921002716637683303931423658281999124167227266760280524431849258878700730972102005699866607355792122606494873247981182878065191212572942618561893778371927720111739404786285309000717762102177293718861398171337471297541852256512378691856093206463497, + "LambdaN": 11782987182893554914718210326501279169306375989002973125341504643881470849412226175421462891524240353067521699225733692803991032395489197009974168479101406655097149822559927864344554796093532611573849336276892835775960580321497004899342220798957613801953848568071062829318306835711627567224317037123489225117593006323173858585499902445969373375128810576898145601370398687975295330215843872524251400278076479855257104692428602429897868444213569031059894357222846724374027993740241597985932221301075902882196301002897156685942740777363224748888153868542604534368744870407110815856899675239897152986570899079020257735298, + "PhiN": 23565974365787109829436420653002558338612751978005946250683009287762941698824452350842925783048480706135043398451467385607982064790978394019948336958202813310194299645119855728689109592187065223147698672553785671551921160642994009798684441597915227603907697136142125658636613671423255134448634074246978450235186012646347717170999804891938746750257621153796291202740797375950590660431687745048502800556152959710514209384857204859795736888427138062119788714445693448748055987480483195971864442602151805764392602005794313371885481554726449497776307737085209068737489740814221631713799350479794305973141798158040515470596, + "P": 139176479153773967279867198040774214842415072965696559232282359608920653244074615431471161007108073339609258225655753834830655859950315592071323750696840555108604453797460479756094948458307887284121925090914428643824297637729858395052855490232506468353296656097911975859819978767863593206153567727472985898803, + "Q": 169324403872506535308042833972947554290109471972635143699374539361491402961920943451449696718738091117103799149767565737222866130323277317910893234724073351935462165216929572253223487004731519524428091465185036356217940919283096893456145773400046565086507321949264563763851968294194357333083325970579705094099 + }, + "NTildei": 27614675962046068547899277024084312796497582685326438131432078731429758369955228736078966232403393128519717932564939784746107420904772358229783701588207059455259502618161910840200562051567770503150540817824559139262802984248403951252387873413977355008106117641673286605673821979334260112540436226212674723934025668596683814586848374953337314261405121168524024601419594482398982286084362672637835235444372112412929968968980942937123148031956496114697316134346209311883711414403323563151755622531177732119691877761184209682988185906330347874368302482624988798895942935852694826557449815813302351003550388152422395085017, + "H1i": 6431113384182909633238735270533890104502722213115053993620977130236829370198551248501569796032069702037202811381051140275065033065400513051513774689573749584921645097186942685963412725381946161800634280975496513452451215386741381110837994921210754530681773217824576676463557023271120110820408519087806691363362502124456847610341997858158147081591503609242798303706865052260389704198732799677985358561044377617144422203650026562164489976317516036783899585326759542741886744454091167808061207911250865609347365318991031342604443846756621429590058302014609495456667443382891915749712336044217554586050990442852295804593, + "H2i": 9647213070899895304545545489314767014326385539720042585866749299185066100845041232180578037555000803485730580204882400541828188021255599686464434290802312599551829888662583531925225213912977594992099462337026103732991329467407924365948381718099943036147485903684049900381042343768982656669090540460581470575846096393641694731328042075493461905912861954032859488992894024381503804893255490170284972318987188654388981150022968037175157751993642854582206140234655035181395286498370831319036079788132394295343602294618507323969083126341855392845028280948796398366359377298333522861850206175833611471600956503614218195409, + "Alpha": 22241874725072667204692308812610289066127299489108269961244733385172133954362394582047488572654516982049712646349030451475355491635223613958898835793391729254706767235372291407458539096414210634128458733088329819167948592333242280199797471868770536045432897968732052504025875758452124502810759206809724222692097998887216383920708912379103403526700989121895379665199990683166435670896003390538420576984131925394325854168091334006802860495596594084498646238223156257756084919786361554629416917243860947711097679782127335085305790720166654130406890091765384889434485133073187759626893494460722797968479090042584612939511, + "Beta": 2571093573260319964714649048387524611171933175868911151722592027341660526306296563709595000094301134850714205958620576084719593795039889963648552892599625997322912204722613038490607036524473050349431661483471123471966877664803062929404341849150582848988179468113055446440122389227987487998539521788115119241298574528052663447677635055916202481598839274936951814648859027398882391086272425313516178786807012857187708625368054262003314723325245144173185168615647892147713761201401294485817993808658962231479200971977355861552300124397090311958201639122765550373801701436375562800536759888557431476959788616303682666088, + "P": 82470010445500897959464090334521974601904959706212652452203284466392773153250967683492652719859926586474817067540407823369013018484665707828142125031280983726336037430339217202598055916406387897372623219372343072662858442847532000095316988645606680093116819203367274418119627955206220421585868556441108875369, + "Q": 83711266110166264264695662311891834136353331163135106345289308691523375137820206487171717221457675649516879479145207925919211996304135116463893031325871139029596072500311474095275353820859225881474943491716615397154183385473230000805324471542526227501721661147329313283989456419289701241864123528324232707601 + }, + { + "PaillierSK": { + "N": 26716139754434734686445314550222096104588936426741666446279727517722487186150141180947581025973383530836171897196819740000573912763711197669349270622014942327309383742222164567992836254714811608807185091126270417165850301861419413952291113602917122135751831812891474124511243941588363744124685283326812180660584964734760100279004701523453395647484987371228083082968965650207856158350772551398991509039737757684558137026129469966648999826859454687361174534479043986714057766937838577726973155857054997303711513490741350262203419689251934447136466306871877327635110735946392336672910150278788619518736410255744590771581, + "LambdaN": 13358069877217367343222657275111048052294468213370833223139863758861243593075070590473790512986691765418085948598409870000286956381855598834674635311007471163654691871111082283996418127357405804403592545563135208582925150930709706976145556801458561067875915906445737062255621970794181872062342641663406090330128907194012920036528480948219870254060808231678904013918646980882470896341617067568075310708123982418955557852563088160249045694909469139607967673622054389100294447134865563911318828315073855492083593807470656005836583256383198178346312414184636242357494515593206391219314919738450266032448570412383726051982, + "PhiN": 26716139754434734686445314550222096104588936426741666446279727517722487186150141180947581025973383530836171897196819740000573912763711197669349270622014942327309383742222164567992836254714811608807185091126270417165850301861419413952291113602917122135751831812891474124511243941588363744124685283326812180660257814388025840073056961896439740508121616463357808027837293961764941792683234135136150621416247964837911115705126176320498091389818938279215935347244108778200588894269731127822637656630147710984167187614941312011673166512766396356692624828369272484714989031186412782438629839476900532064897140824767452103964, + "P": 157195707272547056813706581493309443339890228584643666095586828781267990017180550615740796613460100320350692659541626092504375695690981501768099049823317965475424204815426948736325475935606110722836307881607338411929557840219992019035983701447527189591028428138409178931988270133043653421164422822447560362439, + "Q": 169954639461713149134033045520345696023480679285631389036084859661646375650357865647100091010029692526296328661461667553646532741349534906377140137411617243038044667852680501168010023291301175596708017994192699838600695336265546071407857777055077653329093276621570375302292040668844434032674846608529578305179 + }, + "NTildei": 25021774538223012522514445676343385679567089112924175852741802729662317845407345595213350345211026670762963299346429407733323522004313329678390604020271628665021722065367069445442052310209271941461634265020936168706717993180506881711837131834975647253677465520089205756991301551464651542756334243325974554871331729988771796746576621027568906010908081826216526617323234837670265312100898456757598824766782431090758877304230650745706527284233094405546391502233700138409439418378748521861591678955860446534062398595291070216550722719615021630371874239979280096255720768150429468265061539946484117372598100930165160874917, + "H1i": 21017029508561344855287758341029190972356505192091596104464525030677077303801931282630642391484094030542730819262716457288205985963361725728804473772374771173768364359726726477671814263309301327859982377799785495086239170987842451249057608140290889005645334872188403744397009652449739564008626913361344772445493641587352310719167548565192751088106694816664362425680726252339915551306581077753162281968119820784532266585792633132297450921737017072655901963164136055612085230875298591814978843310694724005768889518296232140065309770721224329875667766485304185522658497683700765160825167265938942702484375373226005145531, + "H2i": 283419044560514051168677259322647436426075939534878796681137153390547382246523209380580875413678639973024300001786543548323220844977925634484802020593285375493289450535253715249901848737368181649186886545408893834906028579238272326203570671063591087224951122161571571035507584265457475853546460220590671831113107402044104975451628146684849151837367126611848483941558876700773147033927247080955619728143849071758393551833585358883155737762341751121782016136304998816315402622218964092427384052183102565718287244785893371242649438930507375843455509001590457571269933116980915588519311647207780721166659659398681121216, + "Alpha": 10515385824214600226543994625916308613193786655673589503623160062388860636537420600948688950731218164781075667978643565597746593864434526341958856020151841313594484391084471516899453088935623006409879417929690776364483773301151841012565272602400359387438984433855873432971794133902116763782105305973445785028101343046990433205481813926089536469560822654609120441715769690382506392324529492166224776460030416766429202818019963785475693973310337383376134236551971626955485155016330992216575869376921360831434947114729277691076387809553682589733668991120649636552796518207529586429359801952551333389938237936363937680598, + "Beta": 1790432759518467322868568935704742787892023347962299745975715473652040365907476705913793192056475402106125126487718842755803946962717218619733772397545419946976675533162766472974791499693553263744108112413534989702056908478070550535783522652837396219644531093685637147416770544193822364496517106504094668092100350533876889396815265988694031386081094727939251566312917745196529335717920734010970837814997995247438943011610658893854265243547344207295475386259915412250635344414089086270818052737575034632357702320349028362518845392994985177207174847551854372687066245239705030771294535933583558958070354852755699660226, + "P": 72424645013342009368773943958641590757133866456836512588001481146899177265482648996553382678650217654541563712666988174700563484739255267289478124487745357807696942810335163113741981913331589928566237884714311824017578067750417050341014658290451398085043602315041015054175026292744579621526318702183964548199, + "Q": 86371754164668399511881152069875381476120759712773506255737328039649708190501526781896075402469154147558113275001868234140009136369538546057866927983356126735893002258434703324124680437992817089373838532376254372436878539739902505868059521195120735705268366579118482187871014338786286933551631276687435903141 + }, + { + "PaillierSK": { + "N": 26480175780836741098634213017014316505678985599165214262517889701665404744394758270507513635914396133610421537581235629409728993204130809255517621297196136782883177781391586370200515968185729901382759706783557295939398740557340175319887451318831468702985013726526461735661462893162026674529091272070296449671369879056988656204820610358858088954426176555164587927821370061772927103171836998738219180837140473551203568890399419564429443581174417945918088028399452027089695030291697860991758311104008921784138478886382992033804078734272418259785924819835419641763748926272189451163604533854609617016249489988733825062321, + "LambdaN": 13240087890418370549317106508507158252839492799582607131258944850832702372197379135253756817957198066805210768790617814704864496602065404627758810648598068391441588890695793185100257984092864950691379853391778647969699370278670087659943725659415734351492506863263230867830731446581013337264545636035148224835522105868755435721876631326787981437504718495998719064460101069278023271857044288398484926115676199045540984825994156818548289957866209303481866572935152828759820559750038229874612370108678062066340875450820059792770213836993112842719938853575912167960758626725863180949073747458504853460007471154943269612666, + "PhiN": 26480175780836741098634213017014316505678985599165214262517889701665404744394758270507513635914396133610421537581235629409728993204130809255517621297196136782883177781391586370200515968185729901382759706783557295939398740557340175319887451318831468702985013726526461735661462893162026674529091272070296449671044211737510871443753262653575962875009436991997438128920202138556046543714088576796969852231352398091081969651988313637096579915732418606963733145870305657519641119500076459749224740217356124132681750901640119585540427673986225685439877707151824335921517253451726361898147494917009706920014942309886539225332, + "P": 156949361724291122562755950818781667331203870994275966491016482405577218543154176616215205289845652191416838969961735950109480337432357603003394327020178628480032530400267466714300014982577463739867530174376468824311163106137371957954406865689950567713291603693977101922878031229154874577706684731367986793547, + "Q": 168717957753493638504591754463344412085535692172873832410151440811303340914594245325034123315942423268704760268449369977223383328009641735950960555508967741090021380391353934528233555904075333911589197810366403623952487954148820616391640246993644738128940069126485987342579007708445035518527862947479299043443 + }, + "NTildei": 24946145482253366961629127833783696869916543512237545299987096143242021925044018830904477554372901545802095393979187133249045868555739086306252491191176652374618251300047864971924418715211188610984990497601617891008052122280076788744763646458197623604695028018234843491914834349428819324970989794879067366958609134958130176385754726128930053497316902908249947352650663174262075540687512544533107969292217398874907429383771027858933746331319748559594012303070911842731317881973964773560451616680656770777983638381791471948574799003221337358663390995601511138122057027678807361319533790264020371204224894186746115824429, + "H1i": 18313249351778079208789660950885159261894973866580713405362813940220466243118811901811685861279993810508654812777696787999601922046678403032681675696967618624361869797788770537775724027091311614490574382486385317208162594806205296293287982058873256388906349156691622673825375111309414215596453649691124921055794691045391988874828536298033755859397558058603908370425969029532638826678238910443739398934495818078931197244988685309755538545356552111669994156293590114370744584107294645216013493424841865362307037198485036007078847139750002724598281625500959430284469683022162583258192402309535332905667308197166568976680, + "H2i": 20711289127977534557365167462937600794186509137735833691344357165272553453510110339718879779055348634590193047617631606153174270486198799517908022189966236411479786716262499949863976892701058674202857626161155735545543131678689545132126284090645416156715963523745543845018026811942460452891715895585081227588334452251934596550500613418578840611074986918722765794738175693893350882053318292450512281994534580010771980369790089232599144326477680091091335854312279735225546276931240549872138775988526872488456550730120129428305208314617101388652426019336246941938980360739672777877003522417183787574542851771582920357024, + "Alpha": 961079079388589809862007761269853332363266206353591939746334822895053766126427672541502762189207308910045149092741385585356850494769572898097713135457897918141045677598773217761276419365496984870923291697421116715438430147386871377856679035318261261166616480519852054063287425963534208026587706252049299221643276903125767227968297399124603566209502106166545562493613584851431267619850752074529280712492010402059665792479579153118712144703558469858884139256148291614702889930819630966785526651856646982171323459338573609352933786329975698309398037270604125007555864760472549734126953175591831820706224954429437950154, + "Beta": 2316604249136996527577473703368480214659443879371823322049522853222552506759674227243476721125762009861163434804851016151875320428861104775802584398339261067689542968138033099195140708096860859619633513551854169412878658089979505072820756636239928334028462268982773296205098298373099269497317084829482908712730596018370047153902015996239432615367885733647161830578924701463953183623495641435648617523348264043432783760277576228570447656564810971816462769629104869045347383402951937749418734349762018922250526697218526592684623053260553279613538446687660358058648847285909319285159815985903636491468959766265877148427, + "P": 75324193684345634701244278008355825113523282334114646755563258496334780504776230411280555393557089469276290533061906733944263084707859347439048257428052431137380897435225807391745035587806743037409406939379739495633972697917804239279547439981500943518749523701126786216693896101493895942765777173914561643891, + "Q": 82795926056616513269710900193924984747193863739768814201499677217197644288508737134572504603736131858772662867055474685371382196637413889488628563450371849810050789758101219893665203995642598953952365243086982331018045873925509537256640891597902556231932587042260275173065485448150054492622639576411700481381 + }, + { + "PaillierSK": { + "N": 25075099918343589388720446791921795059693962609655974799840818974040314485659247956808923259200194571127512186146451622428306265202048418747866575519853869680976179576378155819730004672484810708478499397330279928875213660645501680390637079922651958403980136418641396759552719056879878453564404826773627399847321755318973774099282646090667606179547168048898646838075920761851537517026559746403633231824103698515963657350784363273811623167227499757005831500352795519813474778936522414607131926404404653987865701434837227131548514622117439739571994979398718132745208481689675341848515164923014460924646947481269956961217, + "LambdaN": 12537549959171794694360223395960897529846981304827987399920409487020157242829623978404461629600097285563756093073225811214153132601024209373933287759926934840488089788189077909865002336242405354239249698665139964437606830322750840195318539961325979201990068209320698379776359528439939226782202413386813699923501559297177477651321914641884265478406856080795053590207970099243469502648535121319961914268854833893547553956416636230346931517371160007854562721988234719860846911755394261634257640295303058514672931387364104208174436422890994192523213587028135249843295584859126170021959776184196238081060222986562836547138, + "PhiN": 25075099918343589388720446791921795059693962609655974799840818974040314485659247956808923259200194571127512186146451622428306265202048418747866575519853869680976179576378155819730004672484810708478499397330279928875213660645501680390637079922651958403980136418641396759552719056879878453564404826773627399847003118594354955302643829283768530956813712161590107180415940198486939005297070242639923828537709667787095107912833272460693863034742320015709125443976469439721693823510788523268515280590606117029345862774728208416348872845781988385046427174056270499686591169718252340043919552368392476162120445973125673094276, + "P": 141790080858889163067798565082568699360267645017101950316350289057802605997893843789273930130622161083812777403145225370685716805468546097682715725044081107327541947939681905446477914015746329707396973175882818361505749260474779624280371584390991211161416922944255068030002271928789651820036515627606175073903, + "Q": 176846643759929633571018241816506523373188242291437707343630274306795905731595659974435473155771869645055772034805865442432043327016633643613990331332244972764239007486051985892138731798052207251122865484226200353693892515860671730245196220951456421897200389027167933774593340625832332942489985880538108793039 + }, + "NTildei": 24535812456292946324702596237100823807256064493422101988116258458120645496504642335140356059013560174751878498150389561185940262289574709090944433999230527893816886996941479368193259956866709372069825677723333763182822457624156872771340783421263007220676148123995459118722128873594025276506618641200358423326181723029398005360901627098156138441082786292021032349374293348048281262017724183149152260185497915487474556021539501931226568931286638545478218819693038954021384680226266575540702594205657874951880019414254314089563055861034031606795554325201806169227440122508065705554505477467379241553534852381034044962721, + "H1i": 9288426048707794461832991471309126619837371085840317528274490642829838956756362644425161527484781693089043077479325242048030790121867352384440696525342997668171851653466058283653685494098772044323679802055161952005523208028897059991842494516163026450860817157390516413010355670323645991370950324211502815738151349297759644980827209080529357157400828584270452333885854365795910914790208583722395787883773156330100743777008413969155225883090639356918123719775896835266543163459204541840446613022612443169757648032609061519934759202382518708098786695324409573294243646439334163239202585705098767265043623839912158014052, + "H2i": 19662570636989348670001951096399508149530851507695999743903057533847706010587181050934314645164456353825238435067049867710070341844132470428969707121800541475558410219289868502182563693752013256306162219633617016816145828353004146730516560869106172967795584447375766102055505046120309625953825132276003800616016336324988349651168530353934350055817662869792483934574350881892390687642558978363569063054473859942258732671339651152209984303182673505287398372412083201629609726076351160856215294014522742949190198124251873049921383503222894104415276157401743157380424388208372010114033013253137112331633480745648762645091, + "Alpha": 18648109535677578350174182419734619401758929396681103912588840559248730787014003994374647202628190038912158179605851465903558721263060126706794253423877296941066052784269975766590776054390703308208456088294428785741133602506587760321140671181655771088817387918124600475267863966516896183700662060891927482878916595471574611427497517069605760318606392369072778942900318457633484826829086623494892019150937080515197710368935608763992129782349334067882055847068581487095185418562015298351778389840775252845292857945035589285802368866588348998751332461623617749781107139105475760299897404572613704097739209158827713480324, + "Beta": 660313470667858401148130792675857964921253618850321807994977236964292766625439279276752459632234125485457040486661350400679211411989561436466728935162068131980957884742272358873350733241958636949306123130866015410027335318293098102397639380028418099260847560584713103097107415424842523940174726368096844325376391825321716055304752427284389011591563642866904225517023932134603861026565119856686662541282211618416801713377801196022782690025477613377451768024309623010594293966371591882334022320239282887765556244523989526680927041416152357550940142594452036653590148958802582975476937348110992055727648485335088616926, + "P": 82182898000409505463028997160979384355876510777274705695262586566077063966893756118699037713745114946312412081554552515302159398320983511349645420102336317019644961966656056492907227150080214473079534836276882692105355595029743805899458954921401306950894747500729112506219311728059974814533017587395647607873, + "Q": 74637829321164507758293049323650054827094742446942134495004092634513784777498548138147844639644851367670181453301768762801604446700555351383159800399956666579441644060557665597511213278432575039865883455271985203755655178741105917268103215577596599466456952553120348996788770707651785144726209743368026652421 + }, + { + "PaillierSK": { + "N": 25770141721548730987204072332472144926096055113667827341685255487600901702947504880049680108097201331643041711125686162338242785187029332991152090920383820174742493013796585548588518921268385307606336871626536485520365844518128528597285659731390284511357796019452632613737927642566021402714790786542378784222688111635659880630348633789360694674763494586185752066180783979712939946433415299476593437357192139147559383025427527682085657034900211003693440860669665965157049181378872679388752843559570936546559433824741238728520547746519563812956405501654566042188669270222587904330166581614972631337045680985220935960489, + "LambdaN": 12885070860774365493602036166236072463048027556833913670842627743800450851473752440024840054048600665821520855562843081169121392593514666495576045460191910087371246506898292774294259460634192653803168435813268242760182922259064264298642829865695142255678898009726316306868963821283010701357395393271189392111182632389107956436761554267016461960151784260338240582405761003288594576442288010505693887117954114632649354650953261840908326721532760294459506283391032205861362942232314604381359324906631960491411372813701203026391892707299634136386915126429339305661380128287731625532011525678632978541494449093468355548162, + "PhiN": 25770141721548730987204072332472144926096055113667827341685255487600901702947504880049680108097201331643041711125686162338242785187029332991152090920383820174742493013796585548588518921268385307606336871626536485520365844518128528597285659731390284511357796019452632613737927642566021402714790786542378784222365264778215912873523108534032923920303568520676481164811522006577189152884576021011387774235908229265298709301906523681816653443065520588919012566782064411722725884464629208762718649813263920982822745627402406052783785414599268272773830252858678611322760256575463251064023051357265957082988898186936711096324, + "P": 144471094994361632174761057301514226250544235769718321680792204229757533914901990097221002712695096524308448301478992595057908655807533045142679894818514816891146840581277840914132725981436886674440489478776336130951406107413831913359711567752105686202469123316650656735118350136147193872977556129291841660363, + "Q": 178375762449606124650764198026256528209381829739552579688469768905993259633937288367984660408588813357952225422042011405211094936027157369631748399069086736543176456332965629711901467764870128889296198718562496544785356224506463626822863681043781744663439890330473996531025180121559480381079226668992383203803 + }, + "NTildei": 21087792732704073718006724210354813820723304751895219125666531492964303959373936474557559081219485992141646287695024038689803473518740437409388734708553401337732985860843140604208428126131887372785982762703016190038206052039827825853930550105428659599480000687807532190109363946811212981491367287021202428324352065347861949491560080210713107285487551858856489561616550716983814071569746245998832080798979013745261471824601796729094334337053889530030469994122519634622356364324349906531638640758112393452186484199773400172634812402643891320848471047112277955159917989201672367988365161644298407129209778163987455742629, + "H1i": 16128906224984229277864340521824665825122261942510441702604043745738105868158209157863525680198687056330213281885319592531729130294565833771416178102776871475567704044425045452436041875783355323771886147935262063745834785170226870566517961294730520399402720273694531381754445340691991748873280363396374079652776215831092282131243162290062514492605524521575675847365093962974735791176022529739669256225686526187229198749359980418671994365716472882916903465803922415390675206675773730067934688007124102319261032730070364227242654939133592176629981408805981124145925888660228570020779113119151736604556987192447414658257, + "H2i": 9851977432365942091042223968837199055092785281867774426520485998094195760415225928460219995395472445203821404104058068267237784662212532139124060223115301786957324575763081032486120412296273595775253525452782089630392997146088194631649436052640958432179808023370881579250204827102758604308255506462417015573803343457241802686833763047764425570880288791699910680172809010499338403496957831041673187018687278727590902404276453333395435929791261910522347757670310188653893517032412719849096021581766090837025514505309427642509550661204336541036569971805714032388802497831234946547732870774727031289591894395572489298164, + "Alpha": 1203518491264402840734558039106430565407690917567366792636770926831254210246906151591716016486859448218709439327289721098264159352024397097025580465397903768865093281417842502500472283792152564823540410285428958601675736709207959667149546394765582513400736102269690152431147162293149359230418195220622876645229067380418545557145154128381169741288387488261547742077822837328287293159735625494085227087859698004022865807469054947746791050794871767138504810565107270061528303077334315719030973951809904924744656718548254044432425801637774154631859944033025744390950823538150813566893420163946926942583423586133780782778, + "Beta": 2570501897917963098222991624216628024802927021624180186278805244938245872892665257834801130670699204825799800476403119071749941019871909020966676875902680372816415004696700562845963516277475818229622296600978241797248677804835021733260180960306697729454700300034745059256770711155601830832089036281252093532396305351471942427862002661917713241274115634363357082327034575155954953008778152939116685515196899271336872977459735927647579342010233877723830916280630479313124215507842432273238208625515141719450128260975837611361160794124392658111107010422331101965014616595198391579429618473520627719007638501861928816673, + "P": 75244067993019377687918114238551375866405123366551992169159345775213532181060301364861635029292859934373579206303089426834546525440534498749615700193124878231339197621520488387065345287652616283970339123567268993452693720137103564403239819356233855657991854061045418300078941555718527157616469012379444578531, + "Q": 70064635310056776648957147315110587397816930325413036410655618009578217667968678369374644544166870628384157754658686688480396051466284972191498685947519773949722243058100435014531841539707193571141192706712583641181436161572115192778876806257392176767945252983659910995281822847628603921920914697328426556441 + }, + { + "PaillierSK": { + "N": 27001605117707735462216993559370907025576363079820325318180534690134047782897352986699352155178661349512068835033930599261880443280190992178116301731723948502028475372712570163731312562106700583141099843379771900766027217991711590275583322343639160903052002762497086582998802937120479230388196889652862756088367409807345304782268559374871038784839892529666177613802211615674350199155742148211920522017431935061412098581340939385215543711579288998676243037281576294097510356031983012672482313542381252959808076895266081257506257622285558744999993914283462564285134084787832725820886802101396515425789239835943689077681, + "LambdaN": 13500802558853867731108496779685453512788181539910162659090267345067023891448676493349676077589330674756034417516965299630940221640095496089058150865861974251014237686356285081865656281053350291570549921689885950383013608995855795137791661171819580451526001381248543291499401468560239615194098444826431378044018755737992174269972193304113087650314212963486378523076913685196263707266354910269690711816482210012013600524179081769159735236900122533020341037222440924121251916198201313998812161239233450972181115022868469180830405030304053639183411003684883539512270944203155319320814086598910442953344971220219108837906, + "PhiN": 27001605117707735462216993559370907025576363079820325318180534690134047782897352986699352155178661349512068835033930599261880443280190992178116301731723948502028475372712570163731312562106700583141099843379771900766027217991711590275583322343639160903052002762497086582998802937120479230388196889652862756088037511475984348539944386608226175300628425926972757046153827370392527414532709820539381423632964420024027201048358163538319470473800245066040682074444881848242503832396402627997624322478466901944362230045736938361660810060608107278366822007369767079024541888406310638641628173197820885906689942440438217675812, + "P": 150574808617357497061849280267357369366443753305511076585634002827074150966652306191019260391059416331574908860090629364386681880944753258767406519608369802715614342926967254902937257502824934887177321523348920913285744532851251214162945187554325202889326741956834059834372484690375167537389423883239879517047, + "Q": 179323522743598745262323486377506114845022849387909491062750242454748633656380021481519837993408098705809988672892146482509391356834290673868154443228324643139392180708613129771920733561089416128268525326180221982559703028826200252470226719359370282371265454424688027344886144213200461981709873512265591884823 + }, + "NTildei": 23087700004476980194593337331551070574192919081878401284837775325906253864563721589812066194330730769059846511900766981086736474770582429185966280364685543299856686167693781482952972435165940798741795200022114506322416854426258691362048485182980792902035266506676863050248772433810854473808048204711222901875296171958491837854622944735607685554784396066432419025986579666884675213102118467338971813196059563600225215900590373314389408313817515469986801155609065668403442712907643868020404898730597383554320756396795762757486796954399016934809616146526677948346846759604584844925532714461108890218367538141391264192469, + "H1i": 16136269514060614978769267859514251250048951279831709681250298097805008982743372531252337563872975293717871405098800247867281277199687249261441233707846798068882588387345644502888984237474152281557355311472707527748719783688283477247634461190783027636294862966540221197690082176106342284349823373720174744297429441969744964958072881717587742278590883151152344628056193264753010289089110491192759546471619023441007898783805714870322074011835569184880952034177169212637534104160715805166378240407139319735841047714994046807547528894886945799211743256613675465413798762863143000246699145201977310014561762752607477281554, + "H2i": 1827622695675242162610182631729087432941649762421878138142415662880096901812738722387041761073180357067309277890887033198485675466265058549642923870373160128676955760413154877068192849541865566659080297439182135699059967672359874952927205606420544169388940956689601449871430479301242895226785573382555025437604789704514514472848668574821241506183124453157515268551714969741536515194405243288200831622928730162415557494803772108254606267487094209439289960361115849176589228130298198179490185980246138508219270407438420571345253041428796513393171281287870473322953354603896350788592945088678904131306003831745693677971, + "Alpha": 3998788220896738358620372381513138932777186632254097607339177737953748249403270707590288295918565103340598582662906223266685520450157632181544549199036296130805968751335288267475033324741206968051379087471855305319070735909824628495455165960682163147570069874672464234379210077236349046213070795048602741713187835911608784931380129188785238451230690088192910606334932995666241131336346920845881284361760899335647535829130692419793860442697624258018127895309175103445162966139295512260036677848431782840991497200842608937079687499911636538858971527786411008299813332585806829676969931120248654813299620094566503362362, + "Beta": 250996758783625194064267124703865183134591492027465609244042031535716265438015525005134559699615611032146869196659774747896949926229889496079571170609780764690245179864576633929029185598455049582040797499664423574253463572414697446227325363661747679251040272100549488004871819622924057186323605152821731319084814796712192269718385693575959927563627038209191566340672944691845078917935403606837183002474343213119002967121227198464815596936467201619237200195575066250499366755102298110167500346781824144597237041338350258216905185956781427287788337788099939043555602380010728658688470164258144580375863132347789394978, + "P": 75127965180017090666191907716426180868664944876977503041336542588282220859361186303808592932889526678157682448233468221756611925720006810388196319236449928564533883617130006186048097188907843497276961580607071082737570000485242387896789076167088705347126845161336681262678168960801100130160322736069822130633, + "Q": 76827916040171021817911451883754419462693217589853941397563086160749794035376117291058168896508217303356287531468585822264013662948466773200907112500307922186772309393298017597919199235344365061671378668427029095975950696621090478709400973347801044583357823319426409685679311442662621225640501227800523025403 + }, + { + "PaillierSK": { + "N": 23302748979887206813365731351162912918078218708231509967701919527004512901509418034441762936203655867657678871457954791416917680827329066690074370257572609090915311153595029259411285894846505379795773226776256871579581999319479109694789660915123282188212238719022587110461022936757831539305397692283093296747369436537153830007902282331134364284061781999198955778594100046582905092797254296389593029690454181728270437725637201262199932316730084187133202570465337074703268041445783132858602578455191254459764215641302995671008623881772916648048941023215159640248339117758638356920016718043721823408378778661681019354217, + "LambdaN": 11651374489943603406682865675581456459039109354115754983850959763502256450754709017220881468101827933828839435728977395708458840413664533345037185128786304545457655576797514629705642947423252689897886613388128435789790999659739554847394830457561641094106119359511293555230511468378915769652698846141546648373531437145844317301740591931464086601590495757815050243042225782768877084874674816664326471042984167685539948168902732204793561918865378991947268409328178149476598820581657416592576457750856133922159825577028812535720508887506016898538517890857583680650139337349584017746048934106729136001358223028209623910818, + "PhiN": 23302748979887206813365731351162912918078218708231509967701919527004512901509418034441762936203655867657678871457954791416917680827329066690074370257572609090915311153595029259411285894846505379795773226776256871579581999319479109694789660915123282188212238719022587110461022936757831539305397692283093296747062874291688634603481183862928173203180991515630100486084451565537754169749349633328652942085968335371079896337805464409587123837730757983894536818656356298953197641163314833185152915501712267844319651154057625071441017775012033797077035781715167361300278674699168035492097868213458272002716446056419247821636, + "P": 167150282991188460243992336346823320434142052388807860214003444237170760177011239834463480709396960304114312124085816470278462797900499784189640703034874195776965180148046598774162413046096693197642092184449002375311848202575004970186086315741642899526747242678148146765240481014772120702220212479222460927699, + "Q": 139411962474006944177106131859367760446648431180047432295645036807980162870893423226476606895088886053076229263745920382334345681098826419049025048774106579973105220134421700899287249907382293417802472302796368224255757904185877880785818925758349379421313200381322174662678368815491430703442120126039310604883 + }, + "NTildei": 19903824498400778851539192064240880051125977150814422002819338080252032552095576738670094466463234351366144635642956346960430634075253161798341959968009974054626120451751709629573534244616824067099268567062571869474777322407168004614081811456584186554606069439525567877690139530170193564196493186500878460828966194817896003097269442804887727350771322057177623030916946105994388537646518927100070455838435513635931070862635042177166181733891796052673774821665346663954542228261906537986416580313872004251981618907318590719481316442359578256269250767096471090458917992068625446890621598997894739511721599469987978842949, + "H1i": 16210240195359464220736208060859552394703635249780734119437028965346995248632758947140031346216146993578838134862406539974071858712982270604648417602030860502774053557520665667971784651045945766506793729645550541992861062984414041213059243789549996102670362343876282150654554089552503229331397100082376742115576242890140722949904811119824177878945928999169935840773167334579129167986206146762169755091976520455220465533820737963402447943074477158616410101430438135613565694882527719502452921018455396963242416803376356784846522765255139271624936173681497741823665576798047672260756732149506116596135955976990242902249, + "H2i": 11490479228153319532490367867229533868860039152882215741956053920978626691564585697158106531643475341480820145448764282492736413063670356141897376973904609541278168093093562371473412601770951615614535703285537080538209499063546774080654638042226143809049650054225798241490569528106269635680890524773534482710145135734946969316160364398209241914187382919532283051121562366845718296116897858693147713418738010320828917965476103046079393534681564133831281244993569379787069132223514960546859083740848140079436441768649996477325234941941915443606176808143368885927552040214628536712555418240742909347260309875077601387259, + "Alpha": 5879209502884269498045319279712743730559906358301840652856626227725072312318322201190782652046954734338779534829657300241715964814946216826128495592858593795682396839641277114984356166670828933698661215824330935103998236819819364951941019361861463106078048184376446816638367050859048983216896968759159006637362229996397651301135227020682204217565882694664934393081578893273847739743245730652372982826991300296533647131514741555913567812853020532910095416201070903739296586771790349813528542823664046304447588817625337778697385415615429009875272168488461136666101296961509160461528395277214983308981342314886274118564, + "Beta": 685240498001608801876806028501058123622983333333162845238497971443529520217656624227837531637712280451259649459615358216398342589720870194194729880825219753600062656794320602053677315586086346220475820593475790673569020593775295855028383505035283315115784561434855091375057386939385889818725393315534300057405474134093777992596859936229210407672133228610440032065349267031860636197516836734223307651728951543663980168722009896850663194924490476929467316004178323568831760431796349020084008923160245402936123602667561658531707317892817235015171559468213708255549546122014699458752402161568234238705365655734475844686, + "P": 69951340621069159915320409281784539553456618637907941081852230758548355491395040153069042271991504054875349534922597982645970746573882088918721781431143135816276049126870540936313993893342801526080282126913073141551629991424738821386691505394730299531185305674469757953204628352424813892549469267988658427951, + "Q": 71134535527421325908877821670601729543553260769452854191374782534987535105477895388666613531670721568770519152412295958823866710209474118755238633567448636545889743829805458692554578918562350048148771530912772455363523533379964966813447756185606260667244614532586065634787881054949624492169497521341025650541 + }, + { + "PaillierSK": { + "N": 23124728092584617790121604442860268177487181376735771856832697474629023750061210659796104520597193540358156912695302521537178983181582449690887971349386553742250848596178606527833810366070697972927174043733755760161987236421092896678884390670561872514685664217492621048491488512939872835390673528163085538866780977731969099001658629812581821938996949644303101755809782579131213540585998876139847588301300713061489559026530418688406515859577292946628969455991239147532746970125077435415587161829730798195401076950329277587053666289973088452447476542447387849446366639361621705468087768219623147539957442808115364431717, + "LambdaN": 11562364046292308895060802221430134088743590688367885928416348737314511875030605329898052260298596770179078456347651260768589491590791224845443985674693276871125424298089303263916905183035348986463587021866877880080993618210546448339442195335280936257342832108746310524245744256469936417695336764081542769433238252005615907516659047998482755734684059255156104318215080015600655651857544827129063866962989317113550688513939963900017750743181018029235292981849306417632685118298360006664734667561934921211675874836045823780783245893329033584148469517862132590807008025614163037209353173656507519441024616692306571241958, + "PhiN": 23124728092584617790121604442860268177487181376735771856832697474629023750061210659796104520597193540358156912695302521537178983181582449690887971349386553742250848596178606527833810366070697972927174043733755760161987236421092896678884390670561872514685664217492621048491488512939872835390673528163085538866476504011231815033318095996965511469368118510312208636430160031201311303715089654258127733925978634227101377027879927800035501486362036058470585963698612835265370236596720013329469335123869842423351749672091647561566491786658067168296939035724265181614016051228326074418706347313015038882049233384613142483916, + "P": 145072115968680558171763362069417611993317938897136182432737887294183187416692437120491541095926011380649657126279003368433084813496984100828029813324810224937349759287156901698744933664596864360220268022692883268920752024597884476154169020819484510064937280435952404434459033307460983317033465787979181093979, + "Q": 159401604768603410168770453546892857635513195093756936946884660635719049454216784761228313279396067453738524872371487519937929559718272787330353678967816087330026974241200520387372893041264091411829059255544746756566422478717136807996368485903638157767413307697343226614922387599147125340874743635523040853823 + }, + "NTildei": 27767802923717327700184269138532963037000828345587031451741370638401904245811467828858947295806705170321879587520870252565052935695841394474668673571318535495639548868576436364881896119906811818484221133493803456544137445050294108707213301004737728628866611862691363782045722291491675287529391532003459887610123502642073557608292767482402372967718542044402487221809632109532072099793565020849020685032641391246435999228730927459711490307799651005139311697443784925807409328249673139849081441653744391330583151314184372350756558462910039857738191596424232144570587706501639343147751866657136058766945288671367631689417, + "H1i": 6208381716067437983082687109340999526358477219345070115122392188036741894024214867820037124811802866421821984084290838636684573357267270822971128179172208160602267884588902547294910143441755946182999848736603388785467206252175526988860182601184560502932212557156798253830294407584919872546797992570703023969731244686589840987317034720222055961234056046060171483958189622900785088988659511858296810721482323560487984645061273163062012197153773217857102268749281916186979223468612068011952281215521062423435673222341148235917175848627461899108419067436479445044042502639560730045763183702428671798382876723344099963488, + "H2i": 18796476414135709751629048220715294184560704926876063105990029012678981947733068769045257912821160066325546944425876736608540453951014807788517333662608533716273590847347102498348272768441020137027001120357428908714335385665967132589229083845037480940180419673346682545813753758298526859195587641960786610315970846349660333678173933374389394401377115661401125802471702091547415760954354085573896086645062863029149606683838124507222192599748629655825843833502804567843246099029366889207065888345456920443290406375434223893651807850111369354188482610139515167854851061853064300377539272100968902281453695741535079260705, + "Alpha": 9862700642623631148310976264259502526914187788521108628675810653956106435259280551861309918244477573096949769908609453106572399587194024681608864346104731264720235597305314894424146540814128552826679765691624032479334092398807060533990519845701717646427658839584306284680858172663601801069911828352426838443793761022581419009144730125720687976221462558568234184549197516663079816124646705535148571636768591710628672994676656796637077518210918552617778258933433198813738517805953825773599840025343930055907229547683991363681805339706963660208947917815529788885279367607454551566134971929618646249875894249498158464110, + "Beta": 5685580785459934937149528045040854124767855506473361517935663923560792294307722240384736584681584148054335908950830275936922717097566730668129247672283609808651673508408916023531905023516358773886842810651655660037640403535756932134496419756131785430309483334764202455710992779753423408492884425029198611740052065669224186299389931100174093105748833425118910142669678513949110549704177482710509852105179349427377701880481384953276276216972337117914903504441874764118882674934311630870827638737385873815543635693644717863236038196312351835010801106481907185901337076317183004839106845525118767629488003771163019797802, + "P": 85368886831915457326952738244363437873889991593735428842566935405613101343201417161963510335455485461796857264775721174749408091852794494398126735429857321837415130747500861474105659265252370681473522080958782156081121036459508309187566197815676663238876050903068457291642922033934319146106729648952759575989, + "Q": 81317104961172567752241410225315381929460448532419572607679909507645307065157191121732295237305580335176472579623965789229092481601481653704436615393896437994065326288776098958292227762667069779072981634859323533854176089663269284422258255279065191076395996634296368858788165789071278866810587982959020762061 + }, + { + "PaillierSK": { + "N": 27547322071909745226650309844863580276991780675170103574682338171064554604139886362327850194931606500551777777039349254734274545608516089761691108579032875094808604290719428391317659108939762019048280285594339232986577712565763472341180029709644955519227723965579057298824359119160814187688347791126619281633462407848857075445720338668175910651772227997900780891124462745008507746588424644183842466487821041018775945944797765766554126141569069523989269560066832815519819557166474601844743786185799138915704819495432193469524879509348798545868983527569708828321201403391520141108723357504328824567478692437101383499869, + "LambdaN": 13773661035954872613325154922431790138495890337585051787341169085532277302069943181163925097465803250275888888519674627367137272804258044880845554289516437547404302145359714195658829554469881009524140142797169616493288856282881736170590014854822477759613861982789528649412179559580407093844173895563309640816564859480516299954336509611163622690647718989065374360203962457181595964521738734543075295459683698834846826568820459463664105741675182238752991912344042325185476328946488287119695628299432287243767324177575206009952052547366279530483221468884848986095261324020979886441192846845559950921432240616051725033822, + "PhiN": 27547322071909745226650309844863580276991780675170103574682338171064554604139886362327850194931606500551777777039349254734274545608516089761691108579032875094808604290719428391317659108939762019048280285594339232986577712565763472341180029709644955519227723965579057298824359119160814187688347791126619281633129718961032599908673019222327245381295437978130748720407924914363191929043477469086150590919367397669693653137640918927328211483350364477505983824688084650370952657892976574239391256598864574487534648355150412019904105094732559060966442937769697972190522648041959772882385693691119901842864481232103450067644, + "P": 155247059149967354084839294154974543268188254067406366990896286909265502524908949894228252565424734245686174427630700998376591941414806462284396533280399690125804818642035459314482960193990334860865888879440243912359130620742981164556752648332862785498241888203157196500313468650313765588457688438055884198783, + "Q": 177441828674508182962480151693690727208601765702625803725641543736050315020038225203463623003028909103396118379526145840849322716803898584198889202098348475023062080631462568290869569392944229567304282260841537537261643793873258320345787941467148070632436867146403171726024195162895157136156522766942049233443 + }, + "NTildei": 20567074324437004860130961362455025001909801265057178277020087393519916717412950352609431761865185859444779069157443849864051311360855368431238958571177631812653390619282090811098545486627342419303501136755766301034337539118654852778850589405021484139303659750102568696347460295364004011305370787110603469584814549804891518153837066007989945196983414460543106508232589115362933743236629226855288448484395490000780315183835206216531923241370472380752681979742164221198631667219483711699365502635292914877471641645307303031182806223438852500586595433289102954678132364400189788094218342863948952633399455173160198205529, + "H1i": 11583937985507907402892469337634682138766442668881603401866296480365817654208158035911511320132440739369803415367866567622948220064469406785012517544558957767445426275535423663292998900767299085841712066288729178546894279782305926186316125480846193970460014196153742227701018039359932668176524953645003041222761743869767326037957756935910555679472318282383526777449054791316630153461774293621538528106032537470833276118145168677771064665635416097825927883662685229479726580698708577302754754228420496226830187101045964370498715084528292997565523672024323589901791233177218817531702157977515762727676913406391967730951, + "H2i": 4103108526771659926799412070316073724301935320970399212009404888105724812032316256810422705740538600750787752269648061235730430523425793564219922670582462890996160966165633967624994745102316991878457118955665779413462047348974918210666076430008190096910716543865799968546401606093461922063239372076665397726829516108280179009214157980215334799630326163831517853913997541922825513815597958986066300242538358969504993161757325541269519466429783979645822473919517013412314958724001270326219273916439899104467499554711956713891985428773178929660837361857836520617707180174249710162426509665454502015646297117306209530301, + "Alpha": 18055437364515175546735308246436797761201842673094235224735684912300489362965085430955620981078682777389065402599916356464665737240020019911868408275026701341087056490132879002503398931405000817273079457937887605102647641488524890145887586935724681924232727531730511918417230483387660971613708327555587789450502086998436873312567581023888385507738546029672615164687784219579882220143865144440576643943014488912115831127801664928623116931831195867016769776251253742876928822432599682170048710035015887029672180422769191678977752963772904424041789987559418064416702803016211721433235449074143715677399479176880205416444, + "Beta": 2772655598368718945257192157427768052250780519629826196765492520598718221090913380618969152883216174813911738817960322394118610835807090999668319079610470241765049954161544518526650632982265033057808714290159961358801421246773369513512359460990518513582333036492658454335444309323156928537200048841095506763788780988361745373366063384026051446286586601801109452617921463834635272630637868632703464797985934483698374446598576959804826672649410149664315042409247877229290214411896483796854398981954981320619327877680605248553246514091470180811294848573680716971010864761624920549286019963051725408232709000877717303644, + "P": 75298143985762846165037657380932744959855561251302643860714794109876663111265840206141256776373881260388397354971075422494798460027647687404386066916049406413408231286970203311720727797696206115831674439849944837917068773998576340643404812891471699838271803534963296971470882283184232390104271224150911196651, + "Q": 68285462415666471780979397868570186453961206460774304386236484847082141436311645527059130149975344939079236989827241819939080116830315982532162931314204748201817774533137662071484068556666756023184221397688806960841341953417914010402707457779040071947157937215009274922703062286681954021319811102383915407271 + }, + { + "PaillierSK": { + "N": 24103781230937688737884236130945722667654341902440585411476249488195016405492909386069353042333922275101269190084447580578929222037194412822630970754013071228553282337978349864037469501340871443177555389195459432230670167054009955607232453312569884988938406206833104148948926507708785190117181086158367305176526265966086673637647095369991835452319651807022572945778258214239450350661684406662412340516892845427333315594947286468457091234678752016297400772726215733132323022804166158220697637564174360975093981141425619287101576809838796365346438937225097940063116029082221237617418316802497826387413669265630920080209, + "LambdaN": 12051890615468844368942118065472861333827170951220292705738124744097508202746454693034676521166961137550634595042223790289464611018597206411315485377006535614276641168989174932018734750670435721588777694597729716115335083527004977803616226656284942494469203103416552074474463253854392595058590543079183652588107083073298124709370530845218278825091420534120856769378768932203459698177561726457311964604512477670028969418042169533181877968221625812486567943240569268526685113955494069097229786530207197015262134375231106785205316549455073947173495267063439816560966126261857809093038158174708352487891564657781573531802, + "PhiN": 24103781230937688737884236130945722667654341902440585411476249488195016405492909386069353042333922275101269190084447580578929222037194412822630970754013071228553282337978349864037469501340871443177555389195459432230670167054009955607232453312569884988938406206833104148948926507708785190117181086158367305176214166146596249418741061690436557650182841068241713538757537864406919396355123452914623929209024955340057938836084339066363755936443251624973135886481138537053370227910988138194459573060414394030524268750462213570410633098910147894346990534126879633121932252523715618186076316349416704975783129315563147063604, + "P": 140308464431926656593012176409457482947869022025044684032530139849971627864682796472681789840207403625152979236185419392373638893837288588638764753330352370876735088902595087810728472587304390665764115954333942362803734310559247226715494482733929808125229193053504973159820899463809639087141607227119446361443, + "Q": 171791355058497562313021503145820319188941716755814722988190209982559326441878157275106621467660486462122397522677528009719696404398211802685500132914724825202217705990582932215509591916455576278805596436629463353887209400369401244283953920364288498815954583505000646271521100989271482324488932722948326655163 + }, + "NTildei": 24288448491457965206990464943919365037891083187797599814249067434936309576072677925259783415134392502630597159680261044890110355160564655836832395638648567544850049873670853548150697331193524777825266753504024003793253898562258005352624897031991872613724029792013508049844984340291599509724787236007183072607853862627331249227722131583303105067341610475925175434689353247353950179886259390133691897703962514020051150818643683275771705524111339349728939288550254881894334976215631656185980986989238499248437767085106760150253618580278039528162824338616296411685100357014410757503432986155457730355208033364476869644493, + "H1i": 957786091298976028077804235644486007933462014905520880040265088967292685211279414871325392672320002515813794613355587805889312634310947532071226984442129685152628823287837876950526261674705664243023863486158999265912536434988129244587909941065251874659450834582348641176745789072031144910187891009735715190223419284573030091577666020611132437633691868484977170162279638064505362069328763310200720049859068537210043555095861870246473610491954313491026927825061484122803595708428196155322226492131178293790130398330324163157985821036413936034329740007520623768756885997908920433123020266994290134410672777249016752369, + "H2i": 8821038167954332305130754785293438747162061831445869174285394507956323161539634795477840816358431960915540131268138910915675491055992204656453548755955679303111511655317778388918112371744304572461635644513607969229018910417312874679004326442428895129449919627950150478386615302708088738496044532497744942606816497170141698432728541888062595315780624738836763046789853260434966348246080815985980304013575700099926129475954590846922803133473008416045379933285925713792486791237011295134428613318953103040453732347030522139115493440127901885377506401400278502690603713692812941555317829388020722764294494238417099513557, + "Alpha": 7384027124070014341101948839441511698417044581242861991661911097046626828647314494774292009608356406348747651061963585549272097411398123454750886546164986217376126207248551127598909403088859146917353956332843775689072148780409938098203038704410020111125255463320227514854751896616731569119340940609064470157563266713737280512373053429526177246423469227690303568251312746657784530274546335984477375249876216549308807957148433444302226805629716633239839357181979109527598599647998793967877588515049689220894224970416926264151020952874624848954036373933594218893424950824180342787722879752611582593681240111608058777903, + "Beta": 5912084018359510709356677407334179928567353126943715003223522980161918149108862835324275883851161020416014928208122694804092438135580555218221223308533174494323931684004085672488834968500987861876531658848639755856548972796912793409993982051880144037984761217459770404927756388130898577290699365217345539670430881077198890539916910465762952624507411618999551557986028664524654369477172162757661303398250044384149603399400265780419744698932483948434277995525090811403764322257223748586988349733939996894379387987741049616687389241643495685569632841355979892564378027726072130411258536366621247189257715908969376565834, + "P": 81769035332947401449208759536750334338900412549097201138617797420117337426242067831837030275979616570542730151191633442062196563219773389081039945414950471598799022193898941063129977624205087250340933603575322353872028272939971196404653619547468358082113750855146736604189880912918933878435884994990662066329, + "Q": 74259309751424204609960712451952362703454358600146837379708453661801382892660019133746222670307963429683628304340385171071616288621342407452791467374581752902848020886482016913344170395857309852229634729805310790486895517496875679996171089503420508911677388035794864212514555356121862839607423934573406417663 + }, + { + "PaillierSK": { + "N": 25713100084555019186961207379803457557823287383617068489774086177746783352837200690957893475687873984699224135503079885859887330457073155292498766337859368841618317523562479304097623229264124925121222350263799279092391127317650114668314418083255025755397404834246040329761302545423982491107419289988776676242711481501195450747814120980793077246355324698965530121985929738120743031037749774503824187706613598697193100009075679359902040109684669918877841449997892363025814859213733013948873729282407416646221698942241043463620376663434334785196774278838307115297943991194526358984476956237656984616706807496526239866101, + "LambdaN": 12856550042277509593480603689901728778911643691808534244887043088873391676418600345478946737843936992349612067751539942929943665228536577646249383168929684420809158761781239652048811614632062462560611175131899639546195563658825057334157209041627512877698702417123020164880651272711991245553709644994388338121194883321081404670174523500813591235140799604500540356269071443562678703054505969927425681848442886646593055307937413559211302775161092192486848597122014341660916919405151420524405414878100344135898733440140494732023328263853682115496012445897904835156517551631482972318341692371364021045769746409842558746102, + "PhiN": 25713100084555019186961207379803457557823287383617068489774086177746783352837200690957893475687873984699224135503079885859887330457073155292498766337859368841618317523562479304097623229264124925121222350263799279092391127317650114668314418083255025755397404834246040329761302545423982491107419289988776676242389766642162809340349047001627182470281599209001080712538142887125357406109011939854851363696885773293186110615874827118422605550322184384973697194244028683321833838810302841048810829756200688271797466880280989464046656527707364230992024891795809670313035103262965944636683384742728042091539492819685117492204, + "P": 173585844423254872469878612945894611309103160062404554733992686689875324519075803735303303551910879009482014213866385425396919032933652749601876657724428727530475291242884023734872474298608503676478055323839754365994612117915051930940198646309666796191027996424555706520926322012015729782143552829896357762699, + "Q": 148129014609386534995195366220000164764622329902044854713794164305510300409662030913669520457816946394524975179334466816082515526428832784302267598029434952173505729160546149165190425227598224697946176738120299633579108017811918623264550740732830648793880891507004707826867249482913212743023761846944764611199 + }, + "NTildei": 18503977412452181288073242460811243213376077853729950225202078320494553049290179013708649008823287556020955748430422539205101454251384321927100247074445251635103379803795875598911630900120589337496959149432841285175390499615232509118126550762662454480747066127548876669287808868311464601892765502424878976901397702651378662653021600945177785699582814686276879452142304072401352702375299376430930412490243188414697821736314038664512649070958312437445559357392236568057134669442203222315040839216065278831401669429959822887925603904283623751009524862935377231408770988519567312428892318661670403187049495910824974948929, + "H1i": 18104965721049179280288122700143544153070755921794704362590670409989349804891059609936558905691202331904499802966558494745323793288097835436183756246448746627902547904115486352250258244281196876394853893776857137018194059974797804055262010391211985590148504455924010399666302626709623950032452748384876940838390795560289696050506116610301931645230416771055788243999792576224071913778500574673061936464838986790630543120809268517740074059681997040579116886474357597756476114239976319225139867893535357143110808744290368650942477232389147786699789510235788562363932509957171356665127971055492639442789355585479166090326, + "H2i": 18145368699322232855243127293049743646342954798101629115209422121099568723582205053558925059910085027277461466382493319123912771865099852703558443226068619303433893340375991928793769781936385296568364271641759541819309513704901082831259049219555296904980176002465124309501524202392705072224493642132628335436968986776074159139172789688096878182777583542700235901210492179801650631202723385813705535383967503942526895116862220357448989517209183485318360211453544013007300884973873302684595598671220825289508572401089292777352377040733217072129880644469671286938461408133582489038970925680261165805079379324273591721888, + "Alpha": 179846736986286230936617653128884727295255396728854729147883713979820710188928769724170047474486669500106134114509633369505194217535368455947515422309142957272435748221543770308051896686902686357200490476065566051119661923561514592518751946983488195069892085891681153301555081539052508105215500355749034400136557154826530861240266806444413691292675102415787859183870770126693472005332526974890088092046194923654362756298013599846573973639371849713859506709732811363062702633507706484454713586780015325219052187141386233954297976235342752988044388080470280086582502393281251449844036682512369142261390721589358711642, + "Beta": 415134397096713815141018927159697539238774986481589181784421984101433878266741695241639652786923111316278392328078162332302152970508790047430193292327314939243764163830062496063377234147980323751923104503507521807086448322695609725707691653569440879371962748505399859558391866839899340029581760987539577892789271188118998984253780732849250784805833630399555869444873071975038262848117408625356011926934043926522781675609934011056594698123912427732246440047096952429939923178029953200608318203254395396060341814566728320694910411847390542357737683069349807204559854283528740649329268511076193840373378029994320819046, + "P": 68502269340979810333272052958449723975867312387534134399797357476457424848722376815064554055246908247301595895664271296719056311071252223368506822781639349890374887354824452013415162820925374445574742214093850406579740533860368144709116245889215599432574954146813436849127351532923855592330624111667699526311, + "Q": 67530527055775320593163782756048012055064123438619719483950214042603939079132076641546946454003898639241390511253628577898617196693931379825962086388093435563098040110169919315889455977481008103227778321056708046349945465458170848550733936378283705322103654547757107099525014332946047086109440338033396509111 + }, + { + "PaillierSK": { + "N": 25331290609620858781627768321101762479680422628077929914136054613173362271386142484432664786153964603134980470441960571048173422036124808722244199535267868957372002443797164945349546886811507886045977304418286324287442184106692457031823387024228719368116898039688984581799796187501275899708963568778246534620303842265950507963362795621366137670785492926628878447365765992125032867254799015999838587676957200726304764284062325429061034486934819353160807079237299562607542264930897851334802122859602074584459343268108669360996373790233279452783732456576507146014131895702003430497980987901457954380164492073777895589849, + "LambdaN": 12665645304810429390813884160550881239840211314038964957068027306586681135693071242216332393076982301567490235220980285524086711018062404361122099767633934478686001221898582472674773443405753943022988652209143162143721092053346228515911693512114359684058449019844492290899898093750637949854481784389123267309992290825158755030957664969997297170717939877982153739794176531903357644960374815408366586905003702562398479755574277236702533333731193603992651839302931831643053239347704030492051829306431602353199615731253399824122590013505300823928928599946157475659296427559722666669560568982609287462215061772864020247282, + "PhiN": 25331290609620858781627768321101762479680422628077929914136054613173362271386142484432664786153964603134980470441960571048173422036124808722244199535267868957372002443797164945349546886811507886045977304418286324287442184106692457031823387024228719368116898039688984581799796187501275899708963568778246534619984581650317510061915329939994594341435879755964307479588353063806715289920749630816733173810007405124796959511148554473405066667462387207985303678605863663286106478695408060984103658612863204706399231462506799648245180027010601647857857199892314951318592855119445333339121137965218574924430123545728040494564, + "P": 147360647512751857031032212697859360998519371959957671552109090541596028477479885130931068602612231427663167520443141760816601675457505560994501366346860490360662959826111466904379580656886889146416238690924099740976325164035162114996724045871119896963744204052858880062883816581187294294892944464178063454803, + "Q": 171899968120246044416433468673683968351093798704613296225303837776721548856569500052174345264337564173844637252470629194839366144014926584181002034284575408960772826409378323446318883589851980731643873114677769971774868599187515689929151210813072297731794836529699217095976033355052085160841424063871791640483 + }, + "NTildei": 24112837805420410269937874649215787566974706819473850269770008696312798370921039813993547872748358857225639207511733334962417918438202587394605109600668962297905687102143632882982749367161775481012077420107246472888759248878092007054597903076768372528562932347564890806070386889311658522968515061751829638281205651237817732566654887597490823811440962271191055315627780550583579779341570445835710795950991519695983013827617117446484613849263657270512282847776733170854272029903945248881697649256425406788858468856829425269906268378718723439605220415869784395753169103186697223989122654974453901938811766326514829582869, + "H1i": 9114536768171314943127902174905483174802789082458326225800751755010439291551772668673891657068988460193051936505447525873827207185455023845277018524340706207936391189458211621151662519068973150266449493777903840534008178949516831151524415033513463229963215995063486336638565790221605159041350099412746604580621189027120026539182252734191489139683984104975855344374712028152568013066983232100028556037912891865190997715890046875744406332243051840011917170013865696001493445845157377781388705558203113435380723502098658401992145211502809169183586729958645510555244273952914456153502304345673662377876074992337459566114, + "H2i": 15536466835338686821016677991201668754319642993180819342382288869303283571178288331388367609397709207573186107647457240018884500202898281476869624460919579294942407574534010747660325314985634971090201157322345476984361532101659523435800355798349317657231607644732814373279756461899115733473521363598507893318375103648696516825983893921288043426638963402743736072100780330325750994093809321004688078918984342141477450217705942962331791364485194074168729463922407310202459989313505224113884028158905175554228687612463169864924540087277525597830063907978148404831396872579333074499209701135879989398065563889374198252869, + "Alpha": 3803161135753094499217471857050592767584489532339949491444265341893327314347074578569501008364261211617158864198796140080967191159612655184818331908391873122070997940573035111778586014048768231712024836937410465384491301012673388187582924393420844314088377872556195218989200420555802626039304138700883969075249236068418562247922187869802682786733860890563284078345682719032199538080579199424515521479918799247394457682065610602699520931816650494300131929393665936036556777737190671262001825501699643387512762107384487778127343012310084003631000037620283004447666841645613630260140020086074690346239205867833117312837, + "Beta": 5790614717799194432475129005694587505817515496912952554142215012702567825548481362678481215281538470440320688275517813253054301371164738580564321527154749461439924353806046975805795782862713733642990935350336406187537721498007116605658843419132846381173995019123894770025202558221598077188786184920767802262964315313111540214769217917315744908089532079314928666831434913540666448207417313303261294271709423097074769299087081895239246301356614668132179181572655746899872630493158248031862343410545315692437615250708301000263669506283709633009279539114546335072073462681873207002828376706376763931736004831536507223066, + "P": 68133154163261823363102444224314302732520817233429954595471568756264821821004204430614104107043550127759504997968281968857609855349323479915893233152048377998917196615852691903546552308884773489491787098524890364566914957248418475541527965832446603848137359278758725670604047692115926643874441904273481382471, + "Q": 88476888020040940770767045952337328214054897423499934078088811750900664961200195919371508388892001690427223612816996932381452638221636060121696718472873432335074256006234263561940972314578820631007762954198298947745962052414360554732501957732790697362591125271943146286377432362645620756661954455624750464141 + }, + { + "PaillierSK": { + "N": 26923456472794294953433008015984992847243115006033876516710179863104387709100553561351556056172411814593503040527301921908440213314289978782365319581228838299964316686262562979742613566754388961754952457812821433231323130473429641175499810283265566892936298813479754100142748143920576899391081924078338066625269257115097007765409384961120705545088069456449921235662841702270921592461973212110828014720649659279131728220016805657255113680826683102125170473411486802021390279159708018965349847151453118311825620514940472627430937881414970959128436760385325923743847688719699557318786706285584056802072689552593014062341, + "LambdaN": 13461728236397147476716504007992496423621557503016938258355089931552193854550276780675778028086205907296751520263650960954220106657144989391182659790614419149982158343131281489871306783377194480877476228906410716615661565236714820587749905141632783446468149406739877050071374071960288449695540962039169033312469871845980287471756800514475495473172939763845521381577942233313347170456070709055645292238632353737171389180780411839614179624672187582789890108426115940996530884530223805192696058512747677873899010384144161947598479661990783033241775145763597372698115544404957570915720222365636925491510769345010826451286, + "PhiN": 26923456472794294953433008015984992847243115006033876516710179863104387709100553561351556056172411814593503040527301921908440213314289978782365319581228838299964316686262562979742613566754388961754952457812821433231323130473429641175499810283265566892936298813479754100142748143920576899391081924078338066624939743691960574943513601028950990946345879527691042763155884466626694340912141418111290584477264707474342778361560823679228359249344375165579780216852231881993061769060447610385392117025495355747798020768288323895196959323981566066483550291527194745396231088809915141831440444731273850983021538690021652902572, + "P": 179633456305495476644478745121183912845812282260996561820651684278948133417769485054620209776025969599330021162710531469071753597272992491297566878175040262328766686012558122050306830396500374688303585129994564684079626922329539032843216111323160853356998331939434583901474426986924795647515801692007815074007, + "Q": 149879966830937345251305187048530685896377646497881910686305551365279118132062308944917220467358982205458928695745450508955000834209315445247823378384214657699561824086702286529650899729457387875724014616657584048154351635103865859801670357534970324990618267970349831585871834567385410171535349170563546085763 + }, + "NTildei": 20150078533963199194774302598259714839139898896697309690703725556763566315615285297141898936401806133650378900082918388544281395515741706621140592419080667964476063086829596649133314098503928256378579770774685854788494580027535784439893705034577993289443483021772799427304806503677893760816374595702035076960135275418924106999291703045546872806766297184177141586572056587891903637044000737379627365986524117500605878979669562523945795678083040667304307087782596136116179610603633160450215867145872322620848283688013867190051781502717153350909059799863957541705709813575770597371343889192192304118900210455391720197841, + "H1i": 11957831462586566144571331364681345999022686477993953116813643158931690142744280667611514384626265150981279934623463858931031965106720806425759599720870302949536991135009571213681399728897463219353549863425956931064622755974939756261102806640394395368056109458955484049875385488560120081741291271972511053571772511828212972259466966570448224805107607896760812790415228640772674302586917489378006149293947929038297964183120701815883789456803653075793335231024497787028733595164656671232595634277367843777691480191000088281555794511985557278392860874037449548592479792581135120514704938964517223098975211661600099567918, + "H2i": 7592999967039047700837485390487123084018384985816136773495288859472209579688778504409361944451002977817380227378095977004076485974146683933794429557718075800125354189446787394373363018642560767902350122172722958370215251173534772534797526969367808975684153048140678245309400656757831436716084724593859583336572350098522235135516507044125865703324358258291181257276966847871973297658819487220702196368139384379447485794822591422572696008779666220857499349514994770800527410715457851526988029339618638457396808579821433906498925250522238489938851058194734453635046916638112874161619905689060916926741755953564661949202, + "Alpha": 1389752109606547981785357276062142409682387072920731659926364247722593774194086450739792829164514055012494521099175923641277101473369245342486015510653195209804221180507438794928831066901134050606399092048081685718752785731273413396291683130232887252693855638746299794593164957274940615175386519830006500512177597353302299928750173306474389714302701736598898418640242916229243975768407117800977372206041188216665253929735067604393869593372797587564888037764392810143941986713008354064527727127422745701976617708139100921059083860865565893996482193372170112451638037092173646141432063156895707669852314520968490821656, + "Beta": 2300988235878083911723048020315969785388403299048541189433020515224556815621450490363448660909459620448468147031671230232514841536135268750637722497799943039235979237146973896045022760773629739625693868544492072765044831562984803514946171132865947359882877284221124947951138383497571402845171838001905628862525699067939430899003958795820553735708995042785734792477209571685426418427972572917538406666199331034299606608175868887211659916833962583854081508932452396080124539811125344315471657907698254457366213692103991957557612978857362557995839079838443237088995983294060028694270206684814996966870159142292687775767, + "P": 68459834157741941368459267334065833602654052138952269043552345416912558969033652974485145901639387546579079909081242608986897747230095924422675198648621644079012209025151852449220974180291066440343156108299340742126854892773095419696587776855640612006142974148970927088642595093660242792682116023812443205233, + "Q": 73583579269029240590285251755250791534196243692532827798245670130395925642279983036226510372887702064780923058906539921305218226297200343893035665189636426192376357483560888547007475943864204989303256276461841661233886171172968920619705430432160490270480430330721361927712459445657975218357730493821533725661 + }, + { + "PaillierSK": { + "N": 24350620792753198105005685618763101935991564875509875828340910596469617983130349014983743221863191086682094746305301621835305948957821128274908791984023473166904696402179959128465012977054852255444898827001716543020108051804405294654684888539213779062548971200429991953649729452013622144514010019954650891778934721854206748157217655070441477480381253179284780148226048001510899482146083165770946809636049380214325952556284624907207240504544815402327873416821716609427326789844981678262181495367148815410925296594435920237906819000822208447668454514131404460308576236795548663928383417872058752836807781393870114267281, + "LambdaN": 12175310396376599052502842809381550967995782437754937914170455298234808991565174507491871610931595543341047373152650810917652974478910564137454395992011736583452348201089979564232506488527426127722449413500858271510054025902202647327342444269606889531274485600214995976824864726006811072257005009977325445889310890208527394526743931207287197479021647473005331309392851374091534285305754517574797108165941681616915507721862559989936058062774145067230503996400755912660162021502143686212554170698050226324622207941442421000576422884153263089880449734662241775743185800551698938959760219883655904115815007981566997157786, + "PhiN": 24350620792753198105005685618763101935991564875509875828340910596469617983130349014983743221863191086682094746305301621835305948957821128274908791984023473166904696402179959128465012977054852255444898827001716543020108051804405294654684888539213779062548971200429991953649729452013622144514010019954650891778621780417054789053487862414574394958043294946010662618785702748183068570611509035149594216331883363233831015443725119979872116125548290134461007992801511825320324043004287372425108341396100452649244415882884842001152845768306526179760899469324483551486371601103397877919520439767311808231630015963133994315572, + "P": 144961375461353318167424632515930704650232664744884119496132286483623806075222719162999846201191428582309498809145760797175765759794147247794772408233945499716280466440561563169722919597892072786435098029231583227911488884882416737637771145907807555915602901752878809369807616487394804726149956129223901319443, + "Q": 167980061690605785562368023351151817687725568529233409944212966844207105459351411458352747102974588398185438303413744130159358619202378020072093015786259284390722280400132742667350234373156289975245782682319495008842484347633265530269783898899113352906601733939271976639055361617352139879027809301512218632267 + }, + "NTildei": 20183828830400964903764707897984639232620457842358987452503892059334783699660384806099556330053591421515147470479933818536169661773341342868209763363775904259346045046792036331805970716837679519844068685898177421663180128835292781717819299458015564883927129809685720028389697806093751538705820808483204113619522271386991083988141104340162099801851480867275772170920535555896968137277196975391681887513706999781729929549324944862481245745383879811054523332335408999444707398502677842779439204207139677245145037894574296099241511632096691568959488435532346231460101111712410194877539661425264999011495500599128846865253, + "H1i": 3441307184484654943430376502122168185836343204745816981139769447376603412213866594450687325505884394613562314312551759995672273162426503262628193262799068101167772811851854875572301641957421123270982256137456067931797529765064336035339931278755670199596283622966319455168637929590452784706573580279877148527605123029127306045071536908877596790088852835601854642656016627674011046202770664421080469098314458528078320648862352636722392267789419592527772845377736710860214867411755551295503326302345370035340714641149188433862677184866102192662515278706718840287106991189238647395024744499352683084309022781603806401929, + "H2i": 16408439647357202389448698242118403277493157708077166547260303571742595985620913938691264692842011571404596982038311149331207584616085624583948295734220843202037266994681862509187807634341782917585499996942806744739278638867756080260212909310419840001125869217600546966988336896460071159735578813020989332411475501144405843752462794132527977597491031069469461159507998139347838387497674406655691238457663841036278139101710027968803527058630084457525317142889967792475785790739708292766219651352147595921812458749151015143897143529978020961473173441423720394799229430357125319325587521250964703379667582565464464321748, + "Alpha": 5671355346430597108721813527841335645807934548656913831955564587532969573586825210648449625334339464884772014392915077503031785291144159360821488087116662536760962936368041386475727249618427283406841417124885275866268349180098922149418057440733481434988364405866686635272984223646154345444332196008335281273097520171931980605414759206836343049539696922608911753561775895273463788525297339020529135083633111708912194560275338760702794605411715475324462801544792486742764271998153905903928691205544599124861278932682430778537845138808168497392589796430262518541092721002250478822980968482085429436027193611128282562017, + "Beta": 1828520595555358928822984209291195502437736931721675493776383795282883661846033810053366338870451524950671859190780001669033845530057638415247007638013587691807466805954462387172755614035951301055570500180853206259627037860687194302981783517614053686862260086883044730787140030439736463380625983319370658804708052958243454100069085200596208340022620232114183262893521763690033580171292001765464395912619681743445830977949814244812970410736126926062872640811458600798402939410199987809434386137290083021823767934152819403328039993662708822719941028646826078751457635132026018381426747035285718245239552501955822728964, + "P": 71008366733698851659454522285595140825678340017627520455721094617776085072979668997040540914169211562167192002842223703072801194250962755786395663026136724475905105353395045056111825449144491505322144694877205591414378649248005185496935689452083978271819426499580869422493148780482520578316137978002068338723, + "Q": 71061445850796510483726212927024449621439327688821269557152221098820033099723872688870248799683829408062431440772108792020521490699190655598701073526967950704079559624097763427365650184966143428581835278784745694553135542775578708327747961124347855266253719149842792202221669420319199577489150357684737917049 + }, + { + "PaillierSK": { + "N": 20465019082892142211080759299065911275469398066579973549166843890136996562283997570615233677893101880524724404549123636206015536311675629070499867110845398044610595541003597762779299098752618388378888330167740545386364841664230751521703934505658203781652068946064639708524549863267771736178031930887525970396721028608377749788107043258145668138176038940506985916224740978450045803173356429531982186482734683572821395283040524812112247163161534579861181979210978603461396320976171019147666861931449941333161640449985918169731274938740439378961073131714341913321517947593801213083808307326201532143356065393423638597509, + "LambdaN": 10232509541446071105540379649532955637734699033289986774583421945068498281141998785307616838946550940262362202274561818103007768155837814535249933555422699022305297770501798881389649549376309194189444165083870272693182420832115375760851967252829101890826034473032319854262274931633885868089015965443762985198217277015215526507613974768426862188558212188996623371488020159839656407212936707543933521390388797875833077237845447160216336534325477901232810936438947259840789953125953688830024246437322635528695091482940043268141125562375501096912436581031282079578187898813692220175434001541071457458259346651255066538102, + "PhiN": 20465019082892142211080759299065911275469398066579973549166843890136996562283997570615233677893101880524724404549123636206015536311675629070499867110845398044610595541003597762779299098752618388378888330167740545386364841664230751521703934505658203781652068946064639708524549863267771736178031930887525970396434554030431053015227949536853724377116424377993246742976040319679312814425873415087867042780777595751666154475690894320432673068650955802465621872877894519681579906251907377660048492874645271057390182965880086536282251124751002193824873162062564159156375797627384440350868003082142914916518693302510133076204, + "P": 150441584188174680735471854012432090815787524968033910810604082287473668392518874366190761254907917656424825150565522205413335605767095314239150200086850945311208558176205500530633993451331419026098333545306831633695489965778729054297947724967195807610759400625849772333844042774706283936172276672506303218983, + "Q": 136032993758522092143621867279511670243827037545705262438096576483259320354964140077924382447049170164730415656784108286266238488743483463156409906246233138468607856548058140956984375605473251249673123938798999999753533848210708130838252244684581946554382749340567000399096261469352333290665095418407202302323 + }, + "NTildei": 20761896462597281573100962165682433191493015259937593316503709113432133462058097370472065788181940409018165769879180382207557150812606659067643562064260917769435377902021235775806837414771125322595362365945350083780305867555082416511309706475717360706462693009887707980789229729298583318987645319713400170308264508285699174506679619238687235462821526298059696428310002395028992781179013803099818336788465971377536551233929274499599365966551522417038130911903295393638770771576697580539912315435778228380909475422862585557793702310783121396305711056128115527119618461376276336147446370574170359699997150001343866823873, + "H1i": 3009012169714659070721966695759722996983175637731881697812120553208423200690648667552071446297170994849340602221585622885608562401901136734317342280330365973925051860589806485043946275048637195666471392402287782957376472399759953625381067472703748108502482827396341291661891863351724904099876651898863814523018336277541842412984619861956973237628817136279800857842078568979046365654616867792754268205784518828085886629845528165688158207276052704962322882860961210169162249585414673794031977988988120615398969313410744981381580119741066197529387064447978571974322515650162063169266721954425398737908069850511078249716, + "H2i": 3848055292687357360053024006649482449734078153391417166131941069686016052882398478307089585092976563353343726772167549341760796400210070957898766539431106573339585836856840334158333351700686112858861881138305178225905038378213739322068843421115444603615959625980169384617236160322915149772514030585562453509749886017086560657551571792710655123454070336424435184266730724152319586273664684277896348858856675160694243820883256531997309137829354623547833934966449167531094244920261809353519002444149255067822422964079506539861314635909394367784613892805660945765731211464710550440355660335835329773704441530225025792983, + "Alpha": 16821019065849584516365376322845383615245796030124593537994171808097853951577883840231840994134020267802121502844340420156324136024427045065973275627949186622403806238688888799921587310844233463519349889606236925475581245130227287625217215201963501824991457519187547953771498894535395453798446527249192789168790754031643032207926368663204616658483884339901051609924258142649824465298111351082056307412098073460755869051784054535205563076549259994355423900917276045978326354321323853749403912408721249643571671380467416566745796512239810087957415382964749782549843395219223631816393023755885959079183603986153185380099, + "Beta": 1420991908910845492196205922100288654230868353791404758140714855414988527569242361550919162417412548829549961112105547043238187664815358476884104866136577971032191546386128727738341551610098984252828101684925255269155591062328393853183013931780963193243738418851853946173990002107692276750315176990973796209711182469250425164271263000728666438925946217223414510401671987209587309910516170602885721185797302020813684748315806081887535510665759338572373983021509513849540776442801714032720092508336992053769538414743954767623723112417254861629697741471514431517838773941270763856435866415106318444111843186597359305734, + "P": 73936331215093752817189388253867799543776277079566780006435422091479291864069293498400619040829384287398896454865561960320190841667002881950475602646950342079189230892904420679243145394647969607814131941035077086306953479295640378088435049737310881813430875907556289568067129019938024619256878391794271332053, + "Q": 70201943081937904123515276828055660984867827993548742225742133226367564418691000243322462562353954204908467620956541381352061962081762467359987964885645181569902992946130820561808832923251411558253382180948283183209271821485954928765504758234397210595598479313721919423626786383667101872737659922545985329569 + }, + { + "PaillierSK": { + "N": 27020047132193556559042568701500017571776207559743813753361337046541955790686397099262657270033746387819915569714728221505316188425793461580859370424873971323309570120466366177054513179879244433999611260252894481764883122499815766651316166612813752189312784106728820443912046083469860406968728686963401478520905405226347107194117865323607069112095125111222428253670095608791364091636569543495730655296553784279124665586702506205139285303778067833223639467842378049654759342063358586743016539006845059590835514321542147756168216001427467933911366756207369567190370321312874213614476905414506760509570886363998866876053, + "LambdaN": 13510023566096778279521284350750008785888103779871906876680668523270977895343198549631328635016873193909957784857364110752658094212896730790429685212436985661654785060233183088527256589939622216999805630126447240882441561249907883325658083306406876094656392053364410221956023041734930203484364343481700739260288013701413644449185014907764212475746620160257793297301067147166261773318369665836440002188134980756701979010360242875125644069893951117575287957401095840081922958631120491861674512462309462986791020456693882050009229460969920603600133670233056305457712624059575836086453602469085042663126815696628831102134, + "PhiN": 27020047132193556559042568701500017571776207559743813753361337046541955790686397099262657270033746387819915569714728221505316188425793461580859370424873971323309570120466366177054513179879244433999611260252894481764883122499815766651316166612813752189312784106728820443912046083469860406968728686963401478520576027402827288898370029815528424951493240320515586594602134294332523546636739331672880004376269961513403958020720485750251288139787902235150575914802191680163845917262240983723349024924618925973582040913387764100018458921939841207200267340466112610915425248119151672172907204938170085326253631393257662204268, + "P": 154570091449735384194035066224750886223788102299636466210189326173798609684824444231986542228590989245189965149603900942121629964822885398293646036229151300605012470691362777984647296913005971183910976834877977467887174424691019032303805254755010299169133205013364136510342237928726339627711065364367230481307, + "Q": 174807732070082911553800441853893274378096688407205192857771988285041935315005767590864108691692833520530742416378119512766367199167280199779417516811035068885900954109754825035020217169220162433342496573276406188262582654796607694407294160986246657105811868180358404931227462547610335555606189606373974190479 + }, + "NTildei": 25190236164565450311018983996173433003789562608279703976692903891752602146166122082563637117632510852615048504967282179498085192913519830192246741810107968110099786983766321803202071617535321911527107792235742190699038030684042785512621408802203654303858579995632245896001507821641342030428714881212996573132370788574191832941979019509412124158573581539319733188834668063712611601800801425374079060485060788048756937518964299394907607249343869526008293232606476968639266337578587463220029721372047818673226762932818642193404680862997741638050068789986525173474958826054668750867878358959251721234277830400098500772881, + "H1i": 11465027757214731165087612655544496821516913927206672605568525895016058229875742785992083634557170698550197252050981412876792370377398970744487685842715898341248197203908393022783683969388304312040070243947950817998154164251277010631104625105028268123408811427784128044120352537986616353753984802136200777554582665133603272778097611629218515383392012140178079554080505547204501011151200087164479242119696171850081727268681766796879346608621825272322723330528497124495682149426796624543125842985847788058699341069923024397623501174140462496240596206270738552065953163059142738439977861071215930152381690600125849000365, + "H2i": 7065272195241834869287316994805348777517110666197433296202304094726214978541033176123249053111425788021460220112596936725698516936733802800821190677649776434940297926321685607511925301557690727926327095384882191716912341400876732857490647109414031477631343078060265550052776227338804623960447945390473885184865370953694856846981873213250221348645492688790195516381269004759020222899235419188382883221447041640365928147203883294604383277350557053752914044036234251886546278852707638046180674773104212444240303240539649582447661227302733879323313515466413788276264784273184882668283285982608961524095716788622894847270, + "Alpha": 21759542422464569608721312492451746998260255807023234211856018055273228925497052726720404505543750325699982720165628205952809301220274080841082740923774763989173878305520485725250526006317181843418858877016824834931393280045670801508256242498125661700197238337363160970195025844582908003063865001230212437476640119712321765376624217832962858915844397480066917187159599137605200255097074754893133902609254719117180451360824820337942498675940895503429404748122178372511191197833211646263556882713507004706010092940311523170164979524501314721933602128421168343979983135452258466142953036367262770846805724456478760421181, + "Beta": 5970022635942781476439593106816879376247433244867699715475807611660494348611370710841871959750197101640505770406168616770605736568651506560593937767218868062755521955637678402435755282803595980398074144408749502081112283972256050863911532967232169352168353717281769160991547649489978796203880574272561131163971286189188556184484245602599402924069518260240366501169238199227586082184225688277600647128062357371180480820019431720362238272029634287846484906845815291255221021191869769424168515465366330262728309377088241655588390682567963356435756505529505167578410936996443917229025143081052511795535359169152938668192, + "P": 81399208525252074588980925797775439479694668514254912061891109127465180399918842751117202103712770017829220031337403471880996374365542612128702347155167622426786996183829788088190015953982385135978793765722902094952478804420533700066863379783840738824518693498710644379455725031603837323327351851726872317463, + "Q": 77366342440389969243661354652067512488911504444353398673843869834581199970847068934909805243570333539182052201810357223542872273071705207252322595561214669795145253906446874953923818671791008176970204114624302749959719436194567791549075044051851214447178570730003068461875852271615169444887127363840192285151 + }, + { + "PaillierSK": { + "N": 21767501586197148990048606112036030928969515183696914317708400583150325130217478586706257896221493477068318915921490444862421291785880136588226790734674257038993205935689799005359467205073346980518579322869692714921580432349646448320308599466233732499724371694912941963944509595214631511710323786489119971470754642322066987447704854168630483519920474826878691967127822096053262974073457152128456625014277058630686833899431493143524462657272195131079279572150773591093629677378945548661881962135779647655197639964319061967817987200972039064142277569619573396219315057199767316360159737264875392610688190537516328233353, + "LambdaN": 10883750793098574495024303056018015464484757591848457158854200291575162565108739293353128948110746738534159457960745222431210645892940068294113395367337128519496602967844899502679733602536673490259289661434846357460790216174823224160154299733116866249862185847456470981972254797607315755855161893244559985735229263493032582543133637917632012318285025368790204338056300936569296178953549597506008304309627373229740359764809175824533107215715214312313862502490065240497396313170190823631900234661210486061335109810907212328776710741670926405965960202955621300868596591459863200637639435303608941814478668372025184975394, + "PhiN": 21767501586197148990048606112036030928969515183696914317708400583150325130217478586706257896221493477068318915921490444862421291785880136588226790734674257038993205935689799005359467205073346980518579322869692714921580432349646448320308599466233732499724371694912941963944509595214631511710323786489119971470458526986065165086267275835264024636570050737580408676112601873138592357907099195012016608619254746459480719529618351649066214431430428624627725004980130480994792626340381647263800469322420972122670219621814424657553421483341852811931920405911242601737193182919726401275278870607217883628957336744050369950788, + "P": 160450063559110959012904519535975842840594604275703356266890576805667655073940288217779495645051411874462292334250768308675526958809879940089717877393403206307680635567258739247151183368970753247177330286080865387301302670727032181776553548399958210145244816181452771072484029634600203155514332161461660302139, + "Q": 135665272442711402424673813830483040509829485022579934748329646109002961092417668898660520749970900296743822035562373185782721267031886566361836689777239903791156415471305162150930309444387922285350090056423771922963263046903154070433803615308372584336877058098588144012396837023057305826216521632004297980427 + }, + "NTildei": 23920428680532483995450188046702079137304192044984132642479842042640965411470944761701941020339697847333242449366214943551501363126698780053964393582814914031481407555051233949234241940831155258051112008067959217730719548291016260601919872294527627592764084604508433317546125452781003235745278471959217522761591443039712270814642137441502962846456645441112867934321980868351940807608076088053740207627222310606294829694140109693390565363115980050010705502870034536225757584430392709949026040456360695225367828467003026193097481839285677909363407855137504423355546095952325078647868110490699735422540438429286262494593, + "H1i": 8725178802234267572755676827687854525324633398435062936204214458821611668225003626533886991596739457734551771377129519672879165233815037036454967848234580293528657566217447286335719087567691410978056744944430550435276640115774637783833689075744513457315744644310610885962354970205440226790972744338079531858495848858477036897720865485769372896219302462222945100431257915841349654520812568181113734616916956113964465365323657234715268795764463220367277818473830055077964160592618180679965513344787319648979000600615132289606074842580575738726929984557328797993432621732887960796916866175196984710580948208071209882444, + "H2i": 4935297025060699529890782464382458843827484746450395962062530404158733300047177494790404482860989755775226917744545357111972367580878067059688436754809833620213597979809117759333104857885348140206349663352670632171676355498091443115446516567040640119245530005136953615602684546990550144716736501161286882277407003585393557736691569942506810404662459596630095644309234227476549525861980935333759401140150599833993002381266749320125055064912142279603416839768024562640165800068290789681039562712820709711223867309978542299326525249493360672835064525773623865182065664075677185911844930579801106795591825403579158686252, + "Alpha": 4122039064359994946842456206543617656785338865824536032469257008265026494378487499168696863163341900504643816299095895606384653328594728961497196004412338088929006723664073971267432628585170107957971073802716536919543532625125403515689096760752770682326546443210959293975629405688128847133273963383508407257504071850279663011928701303274269022117947038210517579607927350729348983499664606487398332398558714594276562033836290243182108917407806645687516609872443627810934703930431931239477554475139279965808793938404432218256629402394266701121767314795034036394874891456042743870837779054263962728813411106009580108309, + "Beta": 5285585314077245718885628735370659295312504173413762484973432679171062775768245917227087666050608060298829017785039438360377982281695877080936373708886091918826203975127231675313615839442810761197273496584458632521141996731072263592671402009526010620047410750115623688881323545633918092959905145388020554565788545217338904004221627147085436413775724525207126025239179370282893624596104866837059177785464833375839778514358036995581797813026687584282990514415978502928495254588644375837494497655066266380199411963588726442176487585237843257287217365874886883092682536519395603857305052217419713048180964462986007080428, + "P": 74240877399996498621731464779197518965403957340215006398111834847540109515813781239517088511491734475174375600436252769002750543474679194975548136563948210127661874919400645605218940841717010922432899886826997690938057598119053098727885973239572624160339360516746974337991516944913256328638932902222055916393, + "Q": 80550060553748291707205754306698091262911386013019678502786906440661124481547166432924287423759447287395469055172196328128567269208696932326765183093480781006981212112275582710956493009420374812903134323108898602273855214744928929997410536422467212915663259767552718287283506356920687123316315463546692997869 + }, + { + "PaillierSK": { + "N": 27589893972975184579091150242290615415839441615583462592516892833454191725149625170962578770346016971138822607747680026830411483231569106174659704081008959082572948689490869598976416081091423868397949778346098379149279306780010514645575079376331086466440642831393554243818938113085240004198280255757293758766879970549085748596558123058794705396377749066456888182928576481204260206849196457463296845972163154612908489397285615833473466793219196392650672873068973260036725065043010335661990720941626807725992011964673245000492542643186691021807251076795149901011342567798566739409737861652554770208623175046998908278569, + "LambdaN": 13794946986487592289545575121145307707919720807791731296258446416727095862574812585481289385173008485569411303873840013415205741615784553087329852040504479541286474344745434799488208040545711934198974889173049189574639653390005257322787539688165543233220321415696777121909469056542620002099140127878646879383273389342572456640095914971495782671569643653785448228092131435923256624166295757143669884475447542829799836233315632704657071707048909237908586665507518800900596380935198711704563644444549968570608379304582345900636486379733983779283943433980784310374104555486394076930147958263099885971676429389523045697122, + "PhiN": 27589893972975184579091150242290615415839441615583462592516892833454191725149625170962578770346016971138822607747680026830411483231569106174659704081008959082572948689490869598976416081091423868397949778346098379149279306780010514645575079376331086466440642831393554243818938113085240004198280255757293758766546778685144913280191829942991565343139287307570896456184262871846513248332591514287339768950895085659599672466631265409314143414097818475817173331015037601801192761870397423409127288889099937141216758609164691801272972759467967558567886867961568620748209110972788153860295916526199771943352858779046091394244, + "P": 153777563270897277702079974031048180573127425049075807578070570693337951606722247114821066014199592264180676436838011155698165280776348164235253891781377911904954513752677474642005842229581030799165779282993948042022764427390395776755646177857211488935636001792567243297140572641660164496744644743139966944963, + "Q": 179414300669938038664213141772091872665334333836915919166243038664409006909882696061136011007068476689128140493816339268461158098345029752598245650272557746330577789419935437610857589822945839785609474072514605157196805456328327686483718030976369791327497455033211342252301372484694833768525671524812849939363 + }, + "NTildei": 22842412127118898772274658650011562930634868696511993449561784027612226634962587970659594670620200070152873058380090508169109984516767819005670747302246013407258076663219791146116706394854174805786170713408621552959612635264160733571810298779956239741629161288728196002857232730998745036663460100061993582475834259933837824502719614300927629666645824017466634169639449628545588726371189683409955206801848780701126546169048871185166832338414267107584432452560552228793876065087381637707217035268450000111855624622887076027517522494323192132206985863364258000042394695494178688338347621224800942058176714815577469850081, + "H1i": 10438728166063145554365692329540251857414804242439727907792995064405305214073883066324827938160577447229516597572366824497302109762124109694665167200025720501171703586273638024584726876097928269395540599404224398394867681309529003453214910339669861918644203719700904110261928149902279405383927473380352210817061631164653811421383097832811100493483765945485554800543142879126409962838118510624770010916101121899206005293668000078865804260045416736720792734478848696518639038799541192269503072576805466314980162178592469211194620391535116381907232045061261317636065514572489111758290150500899753505399157998387652383830, + "H2i": 20105674488089683353395616783116056112902045363957704080305480742882629899282762738121145229678530846012266117681629637874471359476265562732185333614692886381535647586855357159940081716128075674898007446314719238705335417028035265327399653459394190831387534476295596652300273641708270723346897064856567055762122221083814614217288041228463308209976108031646116106796682683903046557245095512565191813693683510815330875929856119161090940752357199546488689968378438504036057808782244768777522701460510219974365201720934526068392749834414066852306909993496545721993154119849207760700627410818815005295929608672950655903816, + "Alpha": 484449185422062416207968563615619333063482692978197322364997405636113245602538053378348517220028462293694129579440681331689034238612588538343374226467361354787100909527015516032422289963732205520542219381778180661788472485792588810106958621705063426122948676349930844804242270283080247960827028507403406241676498375162076140831282356760020306683698448561781320690645994274501157970110011146795658917990831095877507188517221678738481646738875163840101044831961523550920846015209723802855104849095540126371384539608932349022575711139589681765573533689254240287965880639473664657120358814451677906210078145720398850843, + "Beta": 4066651017730978989491257766873143087477727853069088654772728674437452572453805875641027489716501669479607522740636011086780678867143133555320901607213843864725795097056608155799707887322592690897662465353086015269330536558012091190017384349296421627342057509023565858431642156706388765202653599384160436320649355874395551677555187836133608605581979720815374961918640584064270355905328935225193687205622575483693655765324719218218843209919161612446600127290507071166813586983225423222540560376813889828745277230482734527731439237335436840468333629188190970820568160727737739982917600339160321364010071266797787143335, + "P": 71411260264002239684063995616266806127257816053163408758122801371056562990939259667312370336272204663464683195367028554996123546955939032176602944274062621690280670879007657468372530374278662529957592235824323581490202210531332658865446475354057951414847395038613628397202927799233325020625910252268927775811, + "Q": 79967823150971433336326268592445981272638547011630791401092829777946510495925887285401210456104135437132052378182196783826654158191780853140300835846734861771559078205545083943261307752058087210088919140147304042088640995184164295951206850648748965522443460622356636260247105200832719155047249739026625825323 + }, + { + "PaillierSK": { + "N": 23278255699771527045615142296617020100962716983617509514464060818600742789744003898025772349460166040252389823612058719330045269834083819676524975472666375857668239880721560447577169234664688954861530459742643564212438234158111012393448757693998112611796787818066385433271058836342206862036645246085355652061572759344926021949565990594429645037552120629525062521689346954213469049716378468526659556045637760722209780529536466150184862098115435230880686594842114193866862327797183432090985977585622555184858955168402581420639531532048354879196199660145415717962894727920898791820522587429422725339362965394105862911081, + "LambdaN": 11639127849885763522807571148308510050481358491808754757232030409300371394872001949012886174730083020126194911806029359665022634917041909838262487736333187928834119940360780223788584617332344477430765229871321782106219117079055506196724378846999056305898393909033192716635529418171103431018322623042677826030632712514465787601973991208841807840386404971368557968878002063319113430131884909824963298401412134403774779199142877839253654068291459395864312280951553078064814117793247484610524452884476560896175357439481351322108881721723161534700150518488030665772006947969553125046774776216772174601310994004434925542186, + "PhiN": 23278255699771527045615142296617020100962716983617509514464060818600742789744003898025772349460166040252389823612058719330045269834083819676524975472666375857668239880721560447577169234664688954861530459742643564212438234158111012393448757693998112611796787818066385433271058836342206862036645246085355652061265425028931575203947982417683615680772809942737115937756004126638226860263769819649926596802824268807549558398285755678507308136582918791728624561903106156129628235586494969221048905768953121792350714878962702644217763443446323069400301036976061331544013895939106250093549552433544349202621988008869851084372, + "P": 171979442048430205698847260547945242675062651327606414600241220416480488834674745715709524452963996359966609575227314341709306876669657103743019326266430793745639801326876988246572154297220803062112897289800184358639709837189230610611506915488631068873732244058748210099215929828574760150720398724332372138567, + "Q": 135354873946016539919160916198084114104248035460340169333101607158761700617933903161023434789849495554693612556023396129968247084862859335409042706672577243991594290883811474623364917519448630330395342999639694417782058251412801199184391707680723317545148587923044331627757105167303615986020578660903639688143 + }, + "NTildei": 23615726705702178890292902720783515145021046679899814669925498966844529754794676140383384650490191313988951378455134586807867601886226492851526261640493882104822381585184949331849231792001901653657103967485672032986453447954044856857809966370816177578658177643306923053365756235236788073610478360379135448701449832098866816886888947720443589692392440456607275752411084826761907897214249129163589577231222062630807596702559558204578906422109996720837354734367793898297513067002378897724892468014688831652993317010855481891858484950925319177395595443473345878912751251353785813905994567443439278151636023377040671323861, + "H1i": 20461096972928137985641895979716133366019606240609032762599556302502321216927570885782363659822795803290612026987915427177408985647606605736013363212945850343034852704962021278220953656640084627872541107364649992296380179795965949640043331995807019998742837352769190766202076845382192958877894536287723277955266792972929624235774942320818899629700999645744573793772104452753951344294650306984057278181726643066217008638111438814983220554499068266608819765492609579161671832853295553005318480353224271993011633203109300902428467048626703146143675229690056606779206244336198861613626885426810561968165571900379893550110, + "H2i": 1693809815279571637920606449665440098032234041730472388750908832760431088050787832962536711014150842686725888723230223600192180847188929874917389400293549146596563521823932809766057856501575719468382080937515009248279378248748068257113617125324700852593659798695690746719227100401842708895719451214219550964360078535689581138389844537906130803180733722872998244617249517039793317714589886891308326632430152584233346775754185301948002019864611881590820502521483450653887929518166212515257890016330745982275464629924664211664096764288692264027135191945528758768351048012506026086507404380543266172093395915050029636750, + "Alpha": 17879442672832840843628018791180759648724656594566547332558537483382703929027295702808418953050594610278798516927339254960873799530982461993323945965739557868936821873428210101882364949183706036097861781770987916091547969400446476051222125585282286819948101226422712505558946862373030101379047830980510829675316570895270795214366987698076638020025489841345054872203460605311988312680581559121359114166419246306059513974141619705843649125975379264821126228393517929074061402008072583762322798206352943289590166675697039458026739971581943652479059790739577907791074412001019314860367263415080942026791097753997128031627, + "Beta": 5019154986559116001402021959582691256584470128022997182433265726788696551151680127200750651809367666435414836356446473707352118936765029243710017268493971084639025035885960608123720896040567275867165964431242948729035335968243190378886104368164709121846542454520566488729620792132168996041814400963142970055168421328051446681697153130319100506521755599270085807155644545916761277108826530226630115546585533508053686352166499683649475143531781963173320755802859401930961147515304794591714296975909235568133775421423861541270325961624971554388904109527462501592637922066231522778128496632666520718342164482741603894886, + "P": 79306202079248516218813185260753110322950895596909550545700704424996733226112121176975855505237791912386755132088221253906074946600937702684519939952719189470353502115209111582484794702225658310311790166618243750886204741946421048714450794990315059686178944358173820563943485027778097965459333631374896398701, + "Q": 74444766255808183281101449595164831864234857527243573713639011887626294422268033022624149705114778128663101533699472987343863086051519543187791864039849419576420686116945399579559008762199899685504219434095007765682726275434246560729458161505108510880971770852532695190409905457965021109657748421319485518343 + }, + { + "PaillierSK": { + "N": 23025768238896392603290928541273159383894320619061814055280543312780115622565623990557501704304878949078110786051980996269653113071898528057704365695046918870192831755495253640119148949778446697422873914625413057610737483951727386478571221387527809147240820441510016940959913293305346451555071077738366810924387763881721201769176936957949549313323949366770342848797417535225449218665027176911296383725992255482822449945028182634314716567084875126698914950551374254464505225439667404313637201376939555917832653856436320414555315228966811293682602064890943978607399339207605027992074342674422251001837729389698023035081, + "LambdaN": 11512884119448196301645464270636579691947160309530907027640271656390057811282811995278750852152439474539055393025990498134826556535949264028852182847523459435096415877747626820059574474889223348711436957312706528805368741975863693239285610693763904573620410220755008470479956646652673225777535538869183405462041466469827932890508587477309411467419536723128939029324185412472275962223702328704064896993378392193304506256941850805736999139638962537344680690072877828718833457761330102369290825969863630236270643712319556401121715791879310130806212504334958198924491190938182892915125911810269338742987261111832903544386, + "PhiN": 23025768238896392603290928541273159383894320619061814055280543312780115622565623990557501704304878949078110786051980996269653113071898528057704365695046918870192831755495253640119148949778446697422873914625413057610737483951727386478571221387527809147240820441510016940959913293305346451555071077738366810924082932939655865781017174954618822934839073446257878058648370824944551924447404657408129793986756784386609012513883701611473998279277925074689361380145755657437666915522660204738581651939727260472541287424639112802243431583758620261612425008669916397848982381876365785830251823620538677485974522223665807088772, + "P": 166723076395329623153138233725424789432926842829204828208028687637493652202221117279017337731005096455600648361568251071421103975437387757485896447738395660715649441601232359697695895752456932416021006363483391362387320980020919921547307378256751709638081758968963430804289786008266771058889634916673807136867, + "Q": 138107865670006365006623769605301589051949077683259961941018022643403642015401402224149252008230374640612789069576229951419614312369562294523657122667222936311188868315774839877359653684755363029270360068313816249924562665187271110522869677964275871120335198362275811357532733045616802456973572249358408809443 + }, + "NTildei": 30375374981035999935225575584436675947260587956649627810141364906284018011860447174765346746173399308362968124646442374593432455331285179083199220472952064681048409255116920012037816798463860752940077503715720485507474298113873824526951988201025645572601115915534985919465533701890870011041792050750892745337574123724742322243938667304960663425400879143310682387666755322973104331825971746783029047854005989493676627478228644407934391604965123064063345481650663919751100023093847906736732818338397626859499244634247240694224592964903024831693021344610866063961653746794435130025913082979415482600554278748322944812153, + "H1i": 11002899667082756482718336472435947792678151789832573324024610460014042044685684136096690594899448717117426286293569812050408245232590082618305457370163481753788542752163615671205834298327857879713980340420056136332765631470874019434327955257442632176746777365709775594498350437580613911581411834675424242008060390684688322186244883633140194441848948049600363866334244206115977239020137098564423418183196744233240639556531203606527389504246538686235931669331297189424949916461080627383164599739522510124782564082625168778331326727595556178794528268147118927615795092634709580672931790114218716143069263296170876538360, + "H2i": 7029879915884795718901750114809064618561587612637259017728329591477459564598614276790828664688167858154279021630088246691387321261374879092363216410369473297967926757450892284231426809767508109986446887397418914492044318651763740537941722747544758155355144015684529870219045833281081116703489526830882103012894832236415191223617761128371723128499157180346996961088822393734391815145921594578283534970441392498975325192632682414321758860283324584046365052560232510857897844113569493408603047956549128168720393629999970640489333490433327506308271009635668675715069529675986420055416522567424517449300830970332373500813, + "Alpha": 4014810643541110834979401829193122954636993727950191647153558933872764795040289896312391245719293866835107254673999905613532362558237865533061336613154610448510203089983434809675712576102260274821796661586219052210086118620533127101545980560064015415883044600597937466721307006912290961743738203227869538642598843731657859865066438872012842255366739946936048455374250961814694852769424339780578169080339705264292108872152593521865272428588822282733472563564145916936446995323224123845402980337012633226312552743129392354008472229739076032936947340294901702996748906960400400878492762370531339141583602612561187434947, + "Beta": 7425430664754898013521439098747054261139446148656849795520121825090786468952772043516627824025355476364545859123361332916744259892565247599918865155950207012193707782950424809463420019085550310896052166791745555855556971524139630369309737971637325438582751858067256665061221437969350407372356218861350620058156086213663071741743065201061219287012574296388830163007832344056279722593541943972469128687226174620277468335833762801713110359025490236485134065674724506815032784360187300357400153680213433966900407175103973051724093692945080489903743744779956533580265127085286594297928316138654718436469790850505626681669, + "P": 86233605799910252289623070723664799268428035030546754053461661780732884979093687880579066796930643394230380304138921862243735563215377856124376619883533524506823366804836482497024485496802840665699326080844954669822548210787060034756930210847856064083996956664749536048580940290737225730957397153082491639643, + "Q": 88061303650912661756999970310532198461807229722586869739251483766290250492365458356790296637339781450104667445887591154871234999095895942383060673243855903671790662956397552974611700013450065085186546252465316436249640962515441760093323065508650447589251481419502201394751832985966954335417711938223429835559 + }, + { + "PaillierSK": { + "N": 27758422867008020711780744843446342880191737267244652357944508150157370454433129476620918339916887217209504294946707206450470891872330524389470720261462097922985542215549553339357040637930748384984537167001070193776261862159714617069124812523508089766867647256778225810171629423455564086787714104376158506171504413483151433381328831756556984215812865922390580829627363531845684653033849123776506567447070489154143216020187749169707782468190091069847680352086714071028150805374195413855049165883999095525671991114231219032268351630208987758605830726277601014819043750680645695767246242965014783290410618216620923430833, + "LambdaN": 13879211433504010355890372421723171440095868633622326178972254075078685227216564738310459169958443608604752147473353603225235445936165262194735360130731048961492771107774776669678520318965374192492268583500535096888130931079857308534562406261754044883433823628389112905085814711727782043393857052188079253085585462310252903377447245907501484488912002118494436179973191152994154864773992537076853645379102175654454095018737308380946819569070049349850966327870724393105032634291116829317090080290714015223927298058587411420771099832597251273847362979079190766951653424374281072111394481680955037970869289212049940164154, + "PhiN": 27758422867008020711780744843446342880191737267244652357944508150157370454433129476620918339916887217209504294946707206450470891872330524389470720261462097922985542215549553339357040637930748384984537167001070193776261862159714617069124812523508089766867647256778225810171629423455564086787714104376158506171170924620505806754894491815002968977824004236988872359946382305988309729547985074153707290758204351308908190037474616761893639138140098699701932655741448786210065268582233658634180160581428030447854596117174822841542199665194502547694725958158381533903306848748562144222788963361910075941738578424099880328308, + "P": 173473659373666163877398034198726314376725928495419419441389338286631746484934960673336679133305398341985633414024089292432724128027106973903048507311573189494677912559997338066626104248908470712146719478264816651040536447954166002471431725522523159617055296461205087429725879602370799667456877403453869671419, + "Q": 160015203271960462556941907355288923612135756906289050239591887570743177000929088949462597555560739503249392568689043115381419202022885396242699189033692095323407624231964417154242901053662594365670675518791579539685615517060319208439673042596696321298681605470878464114731400000733907681215162389067173431107 + }, + "NTildei": 26056261811873951356485767975229520012945914828631514605812154487335570343454797694068327616179872169848481364403334790002351759621520859983578360701473952050818831734652199964355555393352991711900155529558602011915048760275706030592541474870787627639829294177734685268552603911090890717964959153288763943434856076720115358182843246698628856602125002496759476016535429741864696780478341593305540120615111238788193776497414561779226807061200650141795868551557308114861874761842615425752134488093278201149501107016121526252409116829732493865451170078078517959720712664574368968043981076277961998780902584563689747929129, + "H1i": 17337051403883435683795251465667349762215816831015718885261962124326561992016376398800010735731393134122284125267332220557250978673680816798504552576119062226586551981970092674919239815194494899426494327541785910198456841505283528660377582001905738408530053345899058975162034139220903646419696715576416724167685840873625482863285258961679569342553735287859625999276550751172157490113108297775835349492467233046004820074716473372761191667990908751815009480906694083564022902440520300987798137525651570087839946453183570762447449478212365639530075273419972427705823134845743616693348308050484570004759052677174176355715, + "H2i": 11909383336287391034274526190657051940780659980526784998885911824946902488089296652808307430734819519218484092419044726286501688633090795518634437262300723354864831186952584676564969139982346561630689780313489043969371156429565217250899490451951590274904171577435944477648467311929732374048894073133771675611752709268788044219107889447628926557910546943067474767338750065034342778553701127583446918320725570914964581677747160824526574897767808534573567724354701882322820106968943042181096931104397048619888442873821974893806772411205015831067804928553706034376678548313118714919072160094849859765876672154454443004466, + "Alpha": 8027074689587172871716866331934648907316836216973157387407630498884862147700962623416024817908590395538137866709395227507376956066146621927901043616573131770765398386742425595539345897700440859883796393816751757419816623478485145034201012927265950307979748072879218814477983167692254833098735695868720845054691062221549349277922139271950497601561440860648750720510898439570324573774430610183499701953937465268754529227415306270520024304826936258702870938822048735316258780217744229788567884920678778740107186703367543804841454494333324573432207611516367476171395263504868239411750510633203965623985317665646858495973, + "Beta": 2428888370167877670897696706036495760922343955411380763652168154001455226568480004987787822746646018989113171296972428327370618481673774063619789537223987981619093989780390566917596371975311131589901828851701048670240368385996697015445781868214486214024944054374039690010459025264315689753170280418004470772154669076134250782259895233507773016472778658000012931571893768241347701736631654474357006319945692286162446273485321423306565136807081229716535126941595397976552164658201652982414322483975857279128034474890119098662289111282828268171133847376974066443803370041056582591570553583855897594131017905880257683252, + "P": 84216162721882122033878644029519541014090400995237137498408102844650330611447175130005633080620654861027987139459750750698860453419128491538374222814235944346837867247371616004283807481453342390955718545054010420534137131828634585190576951253874849057912837990865203675356533710953627111269490860703274851933, + "Q": 77349350082367501664592884332312838206662753874070351224196745480642881076093761061980588630971740852097909045308523015048488630332956887252285715861793563241160463487209335146006424009725216197689354714652815062846593856118538346578179670624829246550925586647613255995822143941348242746026628501922045559093 + }, + { + "PaillierSK": { + "N": 24698013459547975620768486310441638500610931202769699714642759997955116547307259210904552657285835134313163261128234252079575358844781812172753259043038366663041844914909382377076299899058958586341075436422529959183013628784770639592779190097827596158461916230746440160460918439423703294778400524288954854501183065202598966312629801371774097939539173801466455391807870933284832506746505416767335334466013477036638617584074761829555820151716267792125509630870822819540167483062263131959897949873404971801196095194873685707169878932263603148545593452924434567638660822083010862410692567940328071986610545213865762919449, + "LambdaN": 12349006729773987810384243155220819250305465601384849857321379998977558273653629605452276328642917567156581630564117126039787679422390906086376629521519183331520922457454691188538149949529479293170537718211264979591506814392385319796389595048913798079230958115373220080230459219711851647389200262144477427250433003143005297950462616574028060424320091474597861646982998074762795042329941848644071685447477438051049219216091748416857344220490170660116220843678676528576428459430479964866722053201726520200468436079218980551997418366217056795565545185703505998949004538233939377306672833020328506254113321219034891677618, + "PhiN": 24698013459547975620768486310441638500610931202769699714642759997955116547307259210904552657285835134313163261128234252079575358844781812172753259043038366663041844914909382377076299899058958586341075436422529959183013628784770639592779190097827596158461916230746440160460918439423703294778400524288954854500866006286010595900925233148056120848640182949195723293965996149525590084659883697288143370894954876102098438432183496833714688440980341320232441687357353057152856918860959929733444106403453040400936872158437961103994836732434113591131090371407011997898009076467878754613345666040657012508226642438069783355236, + "P": 137706977954421863034824891356712290363794633078002584712573943198087884947057058103142595283928353989425520970487992175668106291406224778107858843159734968039378980893140136382545510100681519297006873126985494390385762437196164009252987130491384078277140825447644281973603844450359121986161434008138397885907, + "Q": 179351938633948548669743332361264800535196219192729513129300840561154537139564661376049368287130246945114658181403272820173025419329701693785209100353734794347931583308163065843908333369270412103252349909450230212789279762633325548161515951026038491463510920167487825823743057449311937492222468767657581678307 + }, + "NTildei": 24690422989147079244331941368070433085466651920553999872824548273581552535357120135000911604521136634710519555286289875846405372918001804165373314164562321255223787113687824913759515848874622094464554627298322659680016818468804177101671951869589058029823229312377322809609112982827997705740693123958029295212552850875435775791134220001046174332855654026068089715299035900787889119173017286792570505203745761312967763842094587925290396463221870721431436845389595408449410670082376354849446181106380378103194199593434589809308460121970844303194183027598598900864864755884972326878177884870736736802032626887805594537073, + "H1i": 18160217679830452657187821763041172090263889388861593820249335706071962684151860423985497229358454693954196412986026677217054321777411226457788594799227840346213571392881864301794083680938872927060963581147057109086554471369015970917818102756628753094521751684846961842998357942002291416101399988242970427154989501845124779251784449001656693716769854363201099524714724151681653846080001290989219062955141437477357929821127788912455713684500175763472483981033448604809490825580691644343341231568488550048731941654578659837669480036582211355621746925184380400617355493278667045571509929146811317819599518255933973666117, + "H2i": 7539909739099262713642749584133631605552390296999256248430709659613203508885331677246698799836601923388268146874402595192676776250980640170779224962773530092755461572163698224655552828772354202127984606620667116445697538062590812517574093672311583704096346609772879388167524016670756329286726333335675524764888348590725818945115080363202291053953732005935767730919692745050363713686359888571746210762783314721367082082544554604421530838727102637305151829255843914970681085131308420369957326865445042611666345414642816205057840869177471083996991269169417372609376541125761996574738020596883716464578915933111084092971, + "Alpha": 17499809289545057508247053676742738858699189284737603417523923783264272744066066317551899856891339867717992338474336099860122449369482625509060694782707572965999027679232589627632818656360950659290204480986385688824842245964146817035794861093222535116000152825551339090318847963991962322801503595572757693229255524429335266085807578648177642868243826848888597812426992184279452491710080076482932823894976828101937270598043252457793739582005204993887862272198416095396225365062250587964761907297125508909788385379380878384431928753096726708641901414961082771759296578142358550406068025073316126864691295655688362408578, + "Beta": 3007501980853376590268461249011755045018420325235745424151352187417385417580176087271593781440749267211749717129725208694147231985832827427313483774562258792643876131658183075068923868109270407106085332690768539032728172643580795495262506985488442286654580582042532322189104643605010632488554133838269338880534921563420786123289531259354017442570009824702471919373859035918430018935187499611925355139474771036658699291768851098713886459552396091711719614391247748258651557645649989291911069580271980252750231650359406526080545479957694383214254305862466845146695916828277476633940397032033875557157312839479146859724, + "P": 72807529977190622812111998404283915725671404684164734322687854011371539771483354907865665882239352935309380084354755280195062923379514525391393574447405248866262694251938815104791759608859502922495932111471572677656401917709164954182913064633625238386366421281490629398851232848933204546972919964407143875229, + "Q": 84779771394806877732702277930972788620750235013529476621786124820270993976511995986813920523380030763492841035591935276311034101557648552697557026840922591305649438050982047921432149368543932057261123174101064295425906153139403839536605528207579311500361760838733230516785449243303229586986458609161807402273 + }, + { + "PaillierSK": { + "N": 24446348958358540933248892204231293629430849569775321492954589875502787329006383780346609926715950068850122750077895664231719644540231029955060972678061159502087135740574647662963171137617718829364615778022290492645582587279104101911166383276539612474572134721162760124152666225326650904020261799761489967084157096256286347621448364048156406286218833053477147756679860067779179759745245826674762509418942599527364001630285299217025001182197732096255633530993347915904386564790679893178767381280788246412141078510405759121831861042869870662373340077665624605061188310978264737992118614921559304100485110454074852253981, + "LambdaN": 12223174479179270466624446102115646814715424784887660746477294937751393664503191890173304963357975034425061375038947832115859822270115514977530486339030579751043567870287323831481585568808859414682307889011145246322791293639552050955583191638269806237286067360581380062076333112663325452010130899880744983541922077349304899367546679839260088287366342944198764729161722830000671431571910151308988604450670327427104895146418969113051819947840932776708474092765707847628029251643745045837098326120812911440937280017136460785900255330016629574968338058182808646517796473335267816244858691787214624450445754847235042903982, + "PhiN": 24446348958358540933248892204231293629430849569775321492954589875502787329006383780346609926715950068850122750077895664231719644540231029955060972678061159502087135740574647662963171137617718829364615778022290492645582587279104101911166383276539612474572134721162760124152666225326650904020261799761489967083844154698609798735093359678520176574732685888397529458323445660001342863143820302617977208901340654854209790292837938226103639895681865553416948185531415695256058503287490091674196652241625822881874560034272921571800510660033259149936676116365617293035592946670535632489717383574429248900891509694470085807964, + "P": 150408133219598354630657923684747751213361363460938193059899227316982034301377397241147721780537849325010949808630771187159952104604518406032110468806501590181439531197926341855902990828374491150219945706606663472995278171110259885875766878761792023849555971272104986653567803552370930076610562860579329448519, + "Q": 162533424456950531724346445951481960272785801618680105296515180460854862300048126815637578737064095348143261528816589803761409181911348136806574876655430630466888530305263459648667738210787932380046572769526174077036072211726351626560897082538215288176039393035624118848833427794759125122983037899025436997499 + }, + "NTildei": 23594865847143620698431849598652734031947325938269168501535241672231316471436506192178894287593981411822739465296092958039241855846865917706058408741695718295155529017343593105380102127965392668599843706493601662605927544268246191675338929241875873425149736481150041453984894967765570932541937316734795256805454665076684149731128455391428943703544430139217171775637772488742365991100577966899574155673332017572750544263471810692774156040315257721658998854768026373497649100127316232490713691375250228410286087702859305265344887783764559697324849528969194115449021859484423495264955872044489721484314433485237296464477, + "H1i": 21761638393100520002380867002075617480056716039003321164752481845383333676921197500890354010535163461417886378451063439115951658364558284509721027792276613040229310218452290840862255062521213648670548418173760894037593232052576651461197003616437227101916097660732274988528632663146154478630334268454519590378432647716629228622223889244145412218183912931421115084382819610937486710549711697725643148543374949674442120250056116756965863579661800365688527940723567913614084494152684984049849783279451503874582963026369439679316159011935637298226304431210838721968960212103948009834278581311752310411260756323265543106933, + "H2i": 7135111567549056816820503534833302685006550483473151514476328649643676099818626327402227364904052977232419350406058069216384475214090805930135153273382731546034480129140504607756634754176505956071904750602726945717476751729257975675736885218961423622664338510704378271011712126481502667090086268388022192922650962294631087728736038078068549780920061967792495061053676862518434387942293855453359738534200403928177463803071373562027981426465735237689098386904966566112359247683567337666435367250588598888215950455214135029933140334355879189602575223516329252718471101838764682868240170436769936980542710980558835062981, + "Alpha": 1542201682758250256508424581919305350008520179127587007271753702409393945623376785500348014925936356016488326541181238986277483221360914838216386429811244246214224731563106081484472010176182721063818289066935930784251616219523310750865702718466847536245052643453365319767007155589060205742447389861818801109469493808287375314591046727013475023345328766312840014783444091075131167823296396591733202559889923720213752305180642420777550637770088348225690499135023428227062255875497548910406135246099241338072389354110266745936310435346897550640968861805019519655820687236938657762882822942057850209802038125865939969895, + "Beta": 3036922711418111568807093809410413711617237695255235976809538967342514884121134832427798061240256939726176216769004146042760264478982816072550472021614150192219299997959700093608526860664848158705149100237576886017088503542677383500231881664786248499938946530684266573739820068674615055269032916732689111241394657027520556881766811192030653019705158245785037190648119005179603353251487926485976138207938818472699597004819951374049912981114612170037439130073812581119438254039337993028349646688570531496247206163618182761049388348119995465287817393440520089592848831087420574577650631954689915099342668061271213448873, + "P": 85587897660528566147647775910126611992257007204124894087376666667208665206404122496767803940736831384240838251802210305813602249622305895886830059313351132998773444569222642296874858312521697619286938325270518595979588614967458300835799491581212972715554869854013643384741166958918645824828514641021019513891, + "Q": 68919983117032161070561374452873635944847855046385190663363814765019775789510011590015382097781220449448076489850755618971771796410551855305560910516075192153534557522848286577582541268461062710114655529023528797385334610416666375708614934874680883123670782903403369619755028911832782094410453383938316430109 + }, + { + "PaillierSK": { + "N": 26275932419800325725321287711032330083159318299322200419418489552278075536885948479144461869203208673371972722936567107114938849290734914134620203140813435649862317655046358775568541074968049558199274373884746873920118585247212227630388090731098890947073704482538015403857760016534088528781787627104309636611393403349487528994912588228130753177447950797764837232034935078396255687740991637757730417084339982872936535073504809902155931687250349241623210536639715485824021896869337148492293278176213303328444245491544827951149078771403814667394562293990257891152555056676168088576622650069514802804198471565761996153373, + "LambdaN": 13137966209900162862660643855516165041579659149661100209709244776139037768442974239572230934601604336685986361468283553557469424645367457067310101570406717824931158827523179387784270537484024779099637186942373436960059292623606113815194045365549445473536852241269007701928880008267044264390893813552154818305534148055948276127788136292954606947757843247270488805144658776288899729358664946566967290328393223143041896165501508430149565944779203300263932734473914395377068113912317002606017166693890843374089234200543756034186797373517640088086736071046488623723764339589443346251656500040332623883818296206627994419934, + "PhiN": 26275932419800325725321287711032330083159318299322200419418489552278075536885948479144461869203208673371972722936567107114938849290734914134620203140813435649862317655046358775568541074968049558199274373884746873920118585247212227630388090731098890947073704482538015403857760016534088528781787627104309636611068296111896552255576272585909213895515686494540977610289317552577799458717329893133934580656786446286083792331003016860299131889558406600527865468947828790754136227824634005212034333387781686748178468401087512068373594747035280176173472142092977247447528679178886692503313000080665247767636592413255988839868, + "P": 174708723225670121111220164499829879021039540964800372069890553819522977019070694562150781436817531662764109002871811801839731649976111725377161349287610854753665860497151284732375628943046197749093610504493674709196224087344694786870330500761588850210037209278609218355504091456827137711462369891759289445059, + "Q": 150398514365306618225095477721709402911224762259059249675726971998933252004591050061645054990736004924088633739629981240017068147715830915718183718404275840316219808547551858547883315845385418831172166585963641173579259937023839704350759651135691793494989168218672177717805558532022417325099509260746717868447 + }, + "NTildei": 25893715569752446863155646949884217876550635510357076461318744402864301578364237838002781636754933899141088608185660481913514478493973089419035779927383006730499751542223233718263423410614620654385461270337072540799377570377566768816023560597454346957082046999298593220880555163074731128235450531940687629797064005813372931694396267560632978996285622117964614499764405369457978297561765552885444196446528195043018761767407186651350878444155564237515569056173076789385937874887401404111746294147560727568165244598725909477275491372022684510481129154686103582575786169314141369972271676118236722589890477706590881860157, + "H1i": 10766457499606649093961383625737172820829265159778091673356956175583892967708344957306778758109297736814864766494719583532896269669690604203720761720681481841577096555834855336373179101841947503558091014313668078471795844279870577456536834863984179419139359855387399631499068593811712439270160360562675636565805019487999050331836935787661287070284307782537513446216558248545527963220723648909990106237199302557899089960883486907799617601022106284255596257773390438508639262094316323896275842660235880773792657022114968806788989319670364099274825612130059411029425088052542305202787626581670901864049773922023319037474, + "H2i": 9325616643891581826617819705396778390028767082876786273727954466988193819719384830931762518283435276542699503970122515071070882122172378308857660415665458026994975487175196426725892244464316161025857224271432922765820849173429297833462425973753258422098474864293626254011986619475482611502223548565591702144314799462795659062729518239023929692055707637957435350256032576569408119366068811529558260398964299863273092680369125246631691960383613574438161162155447272470532939312425773334967865631206263411126958925534177427869225267695445753342130654559605974957587508553278721992240445269257048113024672077713615461572, + "Alpha": 25723711511941052404007682955383903425161057133881747035201586053447973749350548499921641923234255289498225619500779964906973374039088591245379935798811100552827370660491329925566861397508691323802606492511347628034124541699382369148096112330167999223517908418548245998783833327124297316540768669018046444379380868935997021081756560527451831684575319633694219750299302310910017709590331564627305064219966617353126822667146951527215413078932708087277118565866330440187355789441512352980691198450711650669752862310289485848426484354200360720020179321259631486856838135446828039085530997176642632030760001565994789423082, + "Beta": 2630782297903628421981057315446985117053562528592811893829982938570737019107399882986833363138313781917607777193673435118420565165495725847480413368354756560922867864356375976992639034228042110692174433402892808418538643634314131325729066781811077221027963113337565634414984719325358987194753311293306185205971611865424594023108044560268457021318920830302415265327772143148318450570868965974472018334534449335889237260556682639453039693052221964040523406895280884257744585847438286231862758573146973184078760688540834817926095383491026779005655430836213890806854001837072779499300490541943564237219613499895792016801, + "P": 79399114077951257137447711758318205841277502966383268898995118468042337895570427864986140929621985406538165683398564098633208727274907053456975703789873599626127665278581533934411139319426463417258479572901154652663504341562676189871552156534996663452632478568954382128857474270487923176357168621959682317039, + "Q": 81530240829673829211708443110231526785832088428521573563715778303835602286638924221537841202639800671211140804891220624602525292729796158167755631587862598192662999816802113450156424001501311949311898694010174468044339929961553529931451035564400833535644609837879459240628218537171375078825183313934254200241 + }, + { + "PaillierSK": { + "N": 23665369611627362908732568144764556215489314749845523806293965809454941245759453482427935224497121599171064949930402989236975795657817266655814970360387297719252966105768008199918495293797980322372663590910417824500582200818925844066759529573527102896522216018479611524463926836702497881476175905115686529062276101777201608912573636516771787169439411125263821172827636636434492107275116762256619484395356511675401527216514026803036791338468181318698968729328380190206734483866757121169217351782551271319044093978854862649811761464671176786142895543416434394422833604774898794883904097245435901695324366352007260558697, + "LambdaN": 11832684805813681454366284072382278107744657374922761903146982904727470622879726741213967612248560799585532474965201494618487897828908633327907485180193648859626483052884004099959247646898990161186331795455208912250291100409462922033379764786763551448261108009239805762231963418351248940738087952557843264530983098246544220937385647341998561329142531618709841966805440756788071146869909686956526656627298977532218135748832408768532517549436904820752515944012307914703849314090112103646734905236257962850562874191243993334594058994452490383213585447164182903093422581740300481413255126332613933234428764276730190490218, + "PhiN": 23665369611627362908732568144764556215489314749845523806293965809454941245759453482427935224497121599171064949930402989236975795657817266655814970360387297719252966105768008199918495293797980322372663590910417824500582200818925844066759529573527102896522216018479611524463926836702497881476175905115686529061966196493088441874771294683997122658285063237419683933610881513576142293739819373913053313254597955064436271497664817537065035098873809641505031888024615829407698628180224207293469810472515925701125748382487986669188117988904980766427170894328365806186845163480600962826510252665227866468857528553460380980436, + "P": 173525516596846062473378730183929385906080422964961997531350184546419036191133665431821519012498809675966825635514785689824945110119725186373093340355339521126843284875665594450912600355561598568992730022380887342654322561459427260504748537884363550431761532522694667212749700255677910440030596419147318491223, + "Q": 136379767516320975328963102590735125248267464879175241685404938311930777344163722911744652128259746934998430083334423576146811129474646490820843500948424839672192570810867319424834940954473747048925615573985988637969320914306768759210976111203705037804226908771603164844644144324530124786436241379399561087039 + }, + "NTildei": 23234473896261302165781450598651485869817436767229553675429184637373528970473076207655097233118294288973363520067769057485777047995877946480906034974429206475058980073546561210463834756096789947510964506899961040038180528029714602778999398342901044429136328292232544761810775009777049496802939896686028209172328622072044936100145625047620955467486428072087463747205989849648402038666785855373636595779635309472560185318929384969074978420224809658546729085566649263346259133493818640795032713504094960659201162614900616178042353399554377906277433864964110692390073736553468996997439427166903011218852401195657389201113, + "H1i": 15457417888032451988803342237696904834222464452698904871630274288464624435733580090785858027300388664239046281462735772688041145660446438938257591378536022553149792742416697548175969071681468913921012429645355604159684350400407270612483807941426310338074574758009191125772474240428543496332233333565976361839403936750602594697843798386585448201728051069752197401736407048541808092339307739625762276210478596269673264849579609250711632376299174602749903716500502678629701060559136261566658612505799381195823158832067449408242645440151273350343691563268997736130962134200201072408531133525342066279097238383826824055227, + "H2i": 20536896210685043479047981067986237139158819353163071305862531754675470583480485457565343066081834517813833380010948719674168291603861513281945851969438750561422092190428387598020351907180239321196788968941855117801289176124776001851068578972590507601553597598245570933968468425201812861042667699731656062374652140270446008890490763005197010783222621514965230967686854570050202953811628968681342178730854459492177442571396738987907308396016377363011181812618078462158576765133322205164116430929727002981100456720608253523557836102186011859663049076458588668880051392341647660874837736220825298554047830081976527124815, + "Alpha": 9885052023094509719500572467577234652639013383084923823306015065052968388891527580303354848495219872382113546214731764707666474374407271656598078291009494172835609599698833359917929261828225480744074962667279744252624254123502150453025179928783563337373846083938624672620757871848044918662182907030124259044153871439287158504818873854189929058453612598425601210309601450529531111573922212039507829437170513551308736499982676847784112605141005762280437478129152183505467387497730223477445282158238102170445983894543709147362592936500075360128222832718713743878230136378250701477331368637155091721395373499732354003713, + "Beta": 1687590103006749404632167045941275708311151204219304805970489702723915069037838774538999240050580898673024658981167981563864504623515279492983500446205994252029048516529313023786603127083841606575531777211195028586394470691567713750408525734072721396069675178759839009389858194827406587066060583285018146771617823763639210144824067733403477254474629496632137476625863296969458977772886466045936782811068491399506212972303850793828842590504850804031640597596742838343708928899133267208314733126649080827829842095825057662258951672777725288212244736303268870221469881478523816829653887910197171121940306300734943680917, + "P": 82410631527755025022003297556584693393547181314918641503755358750592755382147096993621087644425600997856363510172255295905511792067851516587309063385404775730186780466396998045019076522997082370258042426732271283373745547031276536085530377359412702466744293674985811059536360741286322834507968685675614581653, + "Q": 70483848580981260414599979725474475816811027405734951190583520125925892804926197700162480292006791291779524336363957746718899692348645139089790596699117213115483251143068385393822216980400104842470936289027715740070757818234675594987508745043208389523829496972816051998813427130515984266040402845645082369029 + }, + { + "PaillierSK": { + "N": 23605299533484155244338286226577800811991453640786012408382045147611586726118629880966186041518833251119937619678342493017764407775044505029508598506144969378895614486904568021623865142071919791145269343730130541198320218014706337044922330526209422402749430365525249308253651979155198544492389747229332804807718659556687287532154709038018125669360367339491103115658343881200113414691992287988239849866170143285168766593472634687807169184215150392153950031172934194797534287436969468929191992469923177262643288497799740743571159182635342229616101290327441278308010140920443654126334073746984701003397260901408349645293, + "LambdaN": 11802649766742077622169143113288900405995726820393006204191022573805793363059314940483093020759416625559968809839171246508882203887522252514754299253072484689447807243452284010811932571035959895572634671865065270599160109007353168522461165263104711201374715182762624654126825989577599272246194873614666402403705280231451762640628187190060745068711870247100608407333167343217731717196438110085433873874074094556820704431236665380306322516217621555563201320069564347065626143580316887640038240506985257200456513129289637147561282389188623646397211446852139381104307239594400047371137002525735946306057621032596285673214, + "PhiN": 23605299533484155244338286226577800811991453640786012408382045147611586726118629880966186041518833251119937619678342493017764407775044505029508598506144969378895614486904568021623865142071919791145269343730130541198320218014706337044922330526209422402749430365525249308253651979155198544492389747229332804807410560462903525281256374380121490137423740494201216814666334686435463434392876220170867747748148189113641408862473330760612645032435243111126402640139128694131252287160633775280076481013970514400913026258579274295122564778377247292794422893704278762208614479188800094742274005051471892612115242065192571346428, + "P": 165272887041307519535595908197672701503927820109112754878317887703657935839901272657370059254536162325630989759229397654992133210992970535629910907642930357898566040806004315333984868653793092737106656851585949433509530330249496623963131537280573325501657769767851909891587157180148352278899887290683924303947, + "Q": 142826206742454731362738749698962830432699025180773546113691307060992044459214795160002042863485791845896367971769906272202390940786936745397636483390875142767715959470331378315130642802159570124623605387634517014939064074008598312858546859342589190597737891963791649492472911515364456112382131545531853994919 + }, + "NTildei": 22345446528066663305590020438361913830694151870849022364405778821403881805016817614773601522607401670101173331296406088201630739075972244938306585480235067979318720678592951382957083282742166305712987511722344100552146703908443126857798655801708464324652393170640537039087336377009467035774524290464199613910708835732417589152467403637726133162330343192846799275019180938514817375094770419093405226781641173387954094919190200362412935439126664429100847345694712305693794439060746896586818064543258581299843911327656738967883335526593424709209402875902534266609083424294161078203488297949208759548160990312530147195357, + "H1i": 5017551238060941620161398362367310820342435895108008063829242496081960489390009519712419683049479415235299382189656190150098434288448544357180020411932136173754450798543877149788025124536075432097498614094657125462583764591061881419260242533111390070571345681806011311832166680240992763377389748422694930389299737898552264064874510689979030486100782999321194713547322661334202113311144982978458850501102699741540233653707348624458278835330143908724914585619517836769426525932210085124745758253522228231988635823659734688777438145455234049010122546343276632365087123869434925507702530657418380104526837699123708364353, + "H2i": 22093615129433862132749253663843116354159921680431569483911893447145303107098695872706218635667106625473745781337903026226532120794708743653641823201138665524543902729621925430961503560204417872411811266068552840723774619976635714842827412584916122073036453721886386568551121157734535494439808211883154573683146465939190422294083752501019200025674010745893658153256356647874232256965351567592260109463200650066826893090980306960741604867379127316987200714889409843335226096650710614125235356821468615644935713198604625775429224768770399958609592597630260321863074432630889822248144274365901992060896696544188244958, + "Alpha": 8719753698677177664958360507623541756985933971090617698811929864809913645904665558240161041050000380202981992209515666219487970014853090270538446209151616794050619732969599130736527973984871343192953309343919027977423861390115171498456042533099158004367690539598553330482379638011785366837735470722753828800317558402368396879066137686424435646437305663923103715807736907889110716163195685817173939035669684400113983929641286093385295743226578212516249806768941223167670419568769046252963282744889502594605217336804953701250452964134192951573698348010812475903320235238525548770076175223724622404961350866298781017651, + "Beta": 2677202772855124717159163401971862890741102401546816760228572452578250224699468540756568870066403987735042071761823738555598434788541389473268728023137189386734463199838246587800384512920141051506741633231801152276871678209113343483068064547702429326271221691319903653994287682969151512930485430332324327204872748803037955582953752682898574762597261908804143515400918051075212574830584444357163742841111429244272936772893213187705020799106910249082224101152156056142124243651705489680787344798758540866575078882105950221883907971182140951091252591158272710895260158175478095383297027890130762282029303994310728888580, + "P": 74017428988003126107595147201751438475076725830250308115086839296805471317102064843831557924407629615142443869214395693962361935639167250542084248858983795342122330809150633707195869080686462423976257531684311459131210587802457080948753006387571126495832007164539888671883882998361202250095633346639254912501, + "Q": 75473597345864486267984030574045027056835325811868301349771779882869344517425552444935271382999721000666898635027368905902168279536374460393970922836286428463556663805025812341867136924991112647412962214567492753548056094170955529840361277778060057304125967140909934736007013681951465140137073232395329670059 + }, + { + "PaillierSK": { + "N": 23519991687887701332483485212941351103217106395045090121159203071468603153822147895833054013278812468662618639277867039268525685116918353168833114455541039622831274814090267992962472428445580157088631702602755255123150585956221863265865091861877127611219468017567962974175994893137868462555608016931588814824454510762809902006813315301878498266313024224232240156817190923591204163450700124518989500699603676943363531988472305121479434251601403064594823495673188630324298756294227620618619760265068702217432544661556683914461696312909230442658830472935970752375913084470270327616304557630238053976366797631521385112429, + "LambdaN": 11759995843943850666241742606470675551608553197522545060579601535734301576911073947916527006639406234331309319638933519634262842558459176584416557227770519811415637407045133996481236214222790078544315851301377627561575292978110931632932545930938563805609734008783981487087997446568934231277804008465794407412073209054169823408315051267837264572895419044620587627558514495197100510274074698430570061055806951627730003639859659387188536171975701561605515930578338319254604822247716649498062014275903480892238278301684220844533157282005631077744993614862474890267702069290360699821831896609812515596191997747867981898942, + "PhiN": 23519991687887701332483485212941351103217106395045090121159203071468603153822147895833054013278812468662618639277867039268525685116918353168833114455541039622831274814090267992962472428445580157088631702602755255123150585956221863265865091861877127611219468017567962974175994893137868462555608016931588814824146418108339646816630102535674529145790838089241175255117028990394201020548149396861140122111613903255460007279719318774377072343951403123211031861156676638509209644495433298996124028551806961784476556603368441689066314564011262155489987229724949780535404138580721399643663793219625031192383995495735963797884, + "P": 168547335708482561144551135869093837739054431803058798524973270409259389557131505015513142607548308513767344468208791815681457966214171751332692533794578884483540326434255649951700778202091721333497674355602440338575049775603934993505576108130741150326430648954392522237844869246469248898843653010263280686983, + "Q": 139545318761772629038661630334875282783131703188006103175188662787743753345419222642336235980441465174136180240544194531420903941435828190051099100721933107331548785364538671670794953511170019099458313702585801886820331973294033293663267135080279821514078296935156405734795895164143773885139149125522140627563 + }, + "NTildei": 23752607312317800056362777847429586586921934965903783538269968851445616919794832691954062544853396063269938947091266796943492604208315473021992303904065746812579797961426123723666901556913799224493989764184606706048526121744613316103407705482374250189302139791762394410814345063076952522461448964626875123530080992136671889650794854115289204612574066425304884357348500989397631732599689037033029455663151918873061228936249578300522495130444902421065605104269052058140865483664519378764485446150946745000181415842754765654980626614175584236009081575641060684092876723057655955223685340540943070565366515546839538986057, + "H1i": 7491723232425967200466868459264536494900588988193440527530226869819360270332011979991733692351798003600627035354959001519989402860787054379799610711252333503801031432778770600011120081761844496405602874774910142311423608813344500878151063311952027254429660919660059557375675640240561237014858184073140405212194209562182906618057780864581267429359413661080307597796455557988590790113332615108669244722249523630702631245914227945061703129004990462006687613779413760265228924567073430342283698794652997369817686027125879842998289832150069770740732790185770634553359140268340820710214444628176259663481586168901214450272, + "H2i": 13880240367748458105648505461444668192418847361140511480466250465492737992773231947830130447663826937534494930092489919101190235549931740627074313797012775279181213542720706165003743741026003879202170770679272163657566238133517932344532221439081327284499103347464379887534601213106248767760584354712932836020316281834789739243486809530526975225101638007173688201937417077447028052125177972087881973260875156401361398086088392265298731287684194771160853015337934166362115801609893974745991349966975191843798553664280407899191951487614351471674266626378551554522052007107259019359108766934182366812598858516458080783302, + "Alpha": 22168273458504136402593077977543796661581841680459347336422202487005823956344453269268585654089899511222355545946704448185960764032021312208679571332738496666601837502577012581928917590240724850857159689970088877395052692996405004998118810916356709035991898711068980279002380531064490521268476355904683132957704573602528219904770911851615611433259388512474624718507073086406340122594863025820082408998363226194766382211931639738429930709513109395876211470261991253908360236389585108244338854350091118569996676068705037869944020755892240480493703977003545914960269029622673761603584928408380459368774828449620821852556, + "Beta": 4368867011820733495292643323120162607067142902994592269630989895866101065889455493250636687860845892389952241270929348845444748610841525223386956863675405360914994830404017671786256015316531337113024092592656865666028675494346836459492272431734202450582639067792761859470087309265307057936607407666920372571532899964051207813438053885592804051908931107306247966267874564522967429321631595369663346343110132788433093418119234916191539313997500008255485465124906099739726702228980434840617517432004004059554082592786454793279236026429174252359015308115324473101916234745466044399771165683071172662738721277190551063983, + "P": 70560270104645717129261253522856354403121841408203470049544843636739277054893923762201273412248144059037797094957217385880994511959739994667762834605861120714229507270900604745250092770816965357578384243948962235254396626158795455007163096063295094799733487682369588924146781265716124936643282895732881787471, + "Q": 84157158401927371048327490082243310018558718836453559837828209297607844613974557313164807350955785120136284783822293719080627116395294171072326360085444170740432431731131367901568242937107147671287929938799421264256909956565970662584636268814730454964713470832225177295971360120517096844804761191226216863499 + }, + { + "PaillierSK": { + "N": 25495781990306014024960781645994288802199351346925861807323432038740329275016095557393101596261327826469136836955246243873454117912032674276319902843741940198734391215069439605967814947426060993725633899733853266054819460888727552404633858671612502864049799352115124729283272129019149235788533364199538896541061981050630454085097849694474068111521214560863721008651032387204335809176753442741296834330210110627789044084204319358725753095724930426003545446545049505436410761914278742594038186406592654517013678056225577341020707804004643055317681990964349540009426104922479905189923010158186612368542414506154866329461, + "LambdaN": 12747890995153007012480390822997144401099675673462930903661716019370164637508047778696550798130663913234568418477623121936727058956016337138159951421870970099367195607534719802983907473713030496862816949866926633027409730444363776202316929335806251432024899676057562364641636064509574617894266682099769448270371162537016306250887818873035065531905043626076179226490557228108502942506960476966756106696999579548784954935358053200047802365887852489157349374377141500177307077242061517010157563884781583365200683034728224236467441988843001873378103966383868169334751418136247788453191018600753184220954999413479388917062, + "PhiN": 25495781990306014024960781645994288802199351346925861807323432038740329275016095557393101596261327826469136836955246243873454117912032674276319902843741940198734391215069439605967814947426060993725633899733853266054819460888727552404633858671612502864049799352115124729283272129019149235788533364199538896540742325074032612501775637746070131063810087252152358452981114456217005885013920953933512213393999159097569909870716106400095604731775704978314698748754283000354614154484123034020315127769563166730401366069456448472934883977686003746756207932767736338669502836272495576906382037201506368441909998826958777834124, + "P": 152813442456605163204753386653603891007807013302559493809303799524947127244864055467400290767135454552144167379199494047408876827037731711410903803773017136732162216105271373319070437864346599049134390648289401464308054828044175432066481266969906788384175272925073986320668124505496029631515291485286249403379, + "Q": 166842534141236420117458561750333156703320295408803061860614131462382796917968433340384330169075496978074966834288718911221271536911493736277942894017749368349634391324884335254652620772682888737477921338479727403777768998274463876494992791226706412955747995724910341962872848451184214295117124193909839091959 + }, + "NTildei": 27415250331439201755743485028462569106153335074612976047453958811717811566256174921188491229617969167569771837519918949449177563677215485730349487915680241556609324457138761947946437627108997661201144534711314751660659875397909742251031805021328014598784460051678374456674011232844117466534805457977092660323315396273639699301754945481647236098770542729658091427401047182184163029694792191957406463856149151722764754927646064069291566262548543437863282404208538450079883482415721423006522374247471493211567893683253884579121161470824129847771011214298485118550937250536144687420719018058729442732372436291938146461689, + "H1i": 12389568868031150844446625276958532410431922576162847272797098032828635835653563564200262468658613327631068452989459653525176166266124777013644115661451664269756657825471174400526423852872233295697445457679114931207886703623413552232141906410948477205902433769290314251112453515675860598629149627222595838831909092498056447047166005393475010327279797496085786340357341895902455478787266157172870012367227312110797498247748932753549892127159176162005107651986248205833886024345475953806587884671116953432417110717752616684348026302180180919695810308952011949471663450224092005619526174751186101703279485508140784974084, + "H2i": 8080438091196915708010273625126799516193892164570746428941442417491502969647586922298641876549466054202737918895713640981952060104739457120809840346905054699422530379063996827683243872458278628850590442273715922423752071881453793110457323319229353884596727603707984741837030689848683177674680686266702950454467123740599346043262441376915978322643912376728418509124688350108418485512193405209224166767966874353185484946925055228132945374862802837314187902976815185162487925453227657738122634939448809110872740263430459201824835710620959870924428471484736061263760917508454626508751323325398162583861933330547034674177, + "Alpha": 14753092287360453203671418862396028709257509800963258634845705676517049176273269126767558360475372868949589642902968745479893090391246301215856179935812783721056914420687014492092410966886519762441712825321176344896287308768866972848204915155577203875224199987923707219707050571724024731473362351852396486434138061676246560869279196457758564598413764827150874520410956396151683468288716459631529431060783615219162944499729911635862213789323871628046319487430508708942067651170491586439774134240773804838732257499779938072943175007572576587727699879688082598982347615151669795112046872183687908878721425381723835211022, + "Beta": 2379190442956496136543945686899123520038513774541641559574073284364131461032194007237091503433568368001797935194111603021324229178734241662176241332115385532525150907464545836746140900608871864757726352426250187582299722858838311530789056760015285620596176209504377945293346670198064021526093003506569907582368512572527007203861177923411794710732170483093733075776621507090359411721000832848880512053342883140179743535891066343922254576715809529375224633198595361634459457927135252363776038502542152114414125499264193059976633852503177673215262124411794218921875352199919808883625775002714687847999506074038224817436, + "P": 82228667676433269128841834978664933496110543612750182971878634104668502491490449886336640641812408795079804671993153362327788914948141848345822098359172199671503903068524643530343427383165417210339060731363080737087926716910987198691854757940128316987829636414239404783326706213428544992702900433867148410843, + "Q": 83350646149701665234240757805177117473591900627143601134872639828965713596017456255984499356426137696373141978929366771724605940978245060817820153691748542914220173785490922190893752471654501796817524901332886154176220505160118142910353469414751074609083908554793702672584240053997908024327225220104381307623 + }, + { + "PaillierSK": { + "N": 20598586411409997058827289088639636850018143644959177174089361161973478822977151641954313789200008369549641775145253816541784456991901183791693252700321642812274688014054467773645216214249448933414549796735250303641086855443942822418895689071194667173147692122739096008404111401138550334231384488714592200190453149684576273049913299299481124548332919804208062970158778597848948434842628364762037556974300970791487149100872870324223820470381650467499400411542109138015531923129762309646441260153889834736275154124505635016052920932631934711137848463878440533416106251712882269879428228509878259479755874088211111894477, + "LambdaN": 10299293205704998529413644544319818425009071822479588587044680580986739411488575820977156894600004184774820887572626908270892228495950591895846626350160821406137344007027233886822608107124724466707274898367625151820543427721971411209447844535597333586573846061369548004202055700569275167115692244357296100095082819397050462431838732462623587316497584295736731680169960595375182078836681038025298976873709619770602672512723663868095696723116744080914699168921624583324965459114922099830062093700103572554511204975232571109762695934024197632712391168881360476728631936284299182518329774668635987724092999115825574278078, + "PhiN": 20598586411409997058827289088639636850018143644959177174089361161973478822977151641954313789200008369549641775145253816541784456991901183791693252700321642812274688014054467773645216214249448933414549796735250303641086855443942822418895689071194667173147692122739096008404111401138550334231384488714592200190165638794100924863677464925247174632995168591473463360339921190750364157673362076050597953747419239541205345025447327736191393446233488161829398337843249166649930918229844199660124187400207145109022409950465142219525391868048395265424782337762720953457263872568598365036659549337271975448185998231651148556156, + "P": 135567550265709806866632234166134269740170500411618336479700898978018633731364072943668984907404057419405714545749036353917924033489948202901628630468181397408654230225746695477209516428505817326600448345195121066962979120693565634441417894886219736532222975637728477989271655548383460747820267430558418742199, + "Q": 151943340209638379369202140067815645597580712322981273339156508120565643437902215767770618319477673830876089529676506234114502990658214102768373443230678573956946774674171414509107556325176872300652295828845371729564549943889973811271648231229499843426619403506555426853497023624222823283749608426001544596123 + }, + "NTildei": 23709398117609740687245066676544324649148256630191005667215732190931355931645437299269823194548941682189597123449629306330371331589565301977978456941145569351940318683189222038052227925579569364328120915198872472961681209822356771715012218821247762707133376310268539928333011473382903415292537633076451163502807766802745976613569326621924391697296018762063650437559148565533611545139054529954308458903350602508695048688797279476847719163553683924886435425866687510973247377984361273090542645915851736473681494518788487126320678491763295719605806533949261505211880405616915975683532764657908147112805059158763251830113, + "H1i": 23154842234598728637356423108882756759409944773989725877954618967361642797646764344604850469570211674569602932462032601030007095205371745568830747573466773911277837484804944094678431921673065933520295398993579186984532225439189695199497203853671104329925105586210793967037784683510561610031168829173355580026000009039165528315820228635620264342323658880767747469171898172047376181539434376229435254921601213712551114148842471150954920616991307958047755166476462971394086256303440875756463890411341405406050256948647892962533576338910197330641859111993237327806296080164732972739684942365773611542070787550569275942865, + "H2i": 6246443154638431932977863686966805429619529010493551474177014786017190037111527512158290863196473283829829817802716267558383203799846108159451454425618338319270376705962649372123484530043145093070200321850031212881790113704417474876107310819984252272405390083863807765602398058960915633386188205777092249755583351129905083108259724252955712221791600996893747200284679850789906850678080292109625335765398057948802882781361923323372422274892762519118970248415956863525960792283232997805229861798014784868724762511857089038866667921403570426718185254284658222082492086869316531495561633117724392220621347068905119850264, + "Alpha": 2262996998071823209916796986037485154941741789024074161733184681388914283540837560788791550056876295340589820247552694314074109970511832324335943780896008882098802181150467897900766473423906369829097818457564792330676491428552983057456113754503750540854415705621692030377684561319747999076702023699104706300258045062631892603588607313255242615628999176146895774530108976262395476837857723859917379026229117276259046489773145565048393739536062755922852325648683661542926366159749042191105527514872934801929006694744435789752412964217629629680647491777016675052081869691726251715220723766330279742952965287196781015335, + "Beta": 2967518709784895641493819579299630461419643611600975729354231762816373276975368096901858672523874722819799940211602780678175512606098090304823324439639955561014459280639682531502452023158462018663882506213242383631794780179103774528953352267803134736911986392014893325708151153224305294291366910338999085365036368090396190298734571042984303013604799809812945580461078331364844916407714625705241980234634022981793380132461565375637339779439604007771600393586521227127691599882098646009748490220184195688714411662731033863636354058226555797673647315248207419426849740166697203557853961647797262458774395926281997613574, + "P": 84060963277763163222212522191385162909150930357614651429787261859109225083377426145273844277465950374529712912558657719506639775073973407432205797724155819056205120799162366600790111372942864358487685159080258566429321578092370330223390628654348432664382980944832655515586287789944664221635038948349094220859, + "Q": 70512510186406706947866602578837989402596958507128134286801510582666888697243491668056739317612628446117397224842181870175940551349815361357334076307867431962869207393014376183077096686988220813440065695936729483180032897973080164444580148587541576642649239353271643845738002575346762071807591802423949026163 + }, + { + "PaillierSK": { + "N": 22180121464207362735976128116631240978913164658256634812977668514009986171914002392778194459858556528231171960676142254191858664096122376582093924022512243676896835669722784891569271003370255244913874414035025803889939615182987908921400226116592787975592655581286945287448840127040679320960440298144332461890886108587572005327484572769987982130860484859526890540072338948943138376813600197395340581814906867123063488519992543393800757981669993845253295999237545044663021222679710632567249557952421998440072959241109910329714216546421448847785831855952840996716913415204695638850991624728609934727375353316839241878293, + "LambdaN": 11090060732103681367988064058315620489456582329128317406488834257004993085957001196389097229929278264115585980338071127095929332048061188291046962011256121838448417834861392445784635501685127622456937207017512901944969807591493954460700113058296393987796327790643472643724420063520339660480220149072166230945293840909500562935222459298172743249546924821536750013563424492952807182066742426286863877466499606998056888553875849347838204633415146645163230837344526886655329860837748680004000298783456353814046517508125339985567317059177998284098970768926832945521507605746109207829424132439441123473073059830971571339974, + "PhiN": 22180121464207362735976128116631240978913164658256634812977668514009986171914002392778194459858556528231171960676142254191858664096122376582093924022512243676896835669722784891569271003370255244913874414035025803889939615182987908921400226116592787975592655581286945287448840127040679320960440298144332461890587681819001125870444918596345486499093849643073500027126848985905614364133484852573727754932999213996113777107751698695676409266830293290326461674689053773310659721675497360008000597566912707628093035016250679971134634118355996568197941537853665891043015211492218415658848264878882246946146119661943142679948, + "P": 158406456987586110787886654267129469694241589989327225986077758562131243821117010977426417711692214356070356641962465786869009675668517856670824628913723814272693782477807087449572584586998612779437210248149532980957092741330744520847193152994323980542562267142681254011405979330373609553385720648494650325479, + "Q": 140020311583293346251767519375366162072393626464063286959412204475392768858998333844186409170215438770879354770278378911255339039171182698256009695634767457079667718526406185109676375798510678032542713976709697377622489686734707758740697165104851125131335936569795969180737380519354078227843513006401448872867 + }, + "NTildei": 22556817737084427348196388262609356867827228024520595255229161722345685573789035752740015552861824262167086825730538229192851160092243455559033560007330875073405327131477123078815866591383596034828157289451473898593323654418853552601563671973874752115864526023247741570733889440535086361376204319182923580088587792185291987271475553247570945680249422851893189440556982785070109100536372514053693514435056908399147243294076299851642357190701013153546535490792812905395928676043661254762240114180831251433054772376368714065309219019149522579682825460670538347031220659996707445257639906546326828992748175042561601918093, + "H1i": 18572855300591056517759535193408915394441089755465521322925159573477794502147943310519053176263911692533973917283795849377677277142284509135377920159757347497192633442836348458344168680954607364328338929077808343700522619921543421121876475323677061701697073369523549696416364546130618731709563558040901665569599164784276629325445429538931816902003391431220606429358138129077912257321502986049124526504579807481102388878884752642851921427956096807136403622442629475523284644731860939758455489095808318967229502715081426310406408797239917483094707590124746707939787572018807914629332719107776554372045479062804640711914, + "H2i": 20752670524284816675226469414261924951532291432186135305653009607402668180507934579522890244886564759765154882293249097654145029576989225392083876184606333861699117887334181355050132729814591406036195934831554669793714286269468359250315307816120933564533393371520313787712857502636535277195258913400547443505915711268494959312402582342977240152521518974455573375951288519353434498370718545041688271566566821534206931537104363019943811638834396473893058171849857269960293299666915110178235184154551603587572739144411382986477684523767057636261596419827868658746102334546759541137016134664359030208519687163192044340177, + "Alpha": 14828837251805176098620220716504457570210921661876984168323954911756192206907956081241082209579408140854257239347155648232442267740420473239481305155700450036662450851999762990560849654576958954957492106644909366783766207205323577958537338802679487300182110963485948119865847008342241305024698710493370182179717746511122548596832098501471473988442833946878293226951132059925176903228685428338784652503336620719173272056767470509935370574109388474263920152373847705015621284254265562907058415446703106792623435541197206304690603790755097488731315756710230508821026538089264151994813772961624045459892587340036217517135, + "Beta": 16444535290818355249379965906470950381861978238807214294793623507889452860109369297414291706614368553372833698207321850797222387245846410689724471150730679834997576905406885576303743237628727718658665654272723424379133049588886160715612441695717298387742548090558351353642698574929533686118548900175321275335349326292288561890514231284365732638921514822178194173288162820414124204128045360528535480330971676654939628062442218450627666981974507442114279508522170221767616045297539598857857699601356099352010418853395762155999328705747283068446076979742069325947792215379742446997892133279644747170842170014159329803, + "P": 70299507285138192139108808715021139023808736307455843939419262209697268978779401087517925695959638229577275292790135263120822262238591026780814367692874780523897416368966776216236918672264360731726051750549315855856494026067640293471720811477573430536884338043428396952526264968319467530257641920719919220769, + "Q": 80216841512106502669750351468691812667945942084464700022832097164024415028650918707543896315108861841816531301216891020230546407211933468738944671079555949982134687233399952997656991310157599836852495631590618089576695760900678947606804890490977120225500475826877368449272675346436137810085729110165398253943 + }, + { + "PaillierSK": { + "N": 21603530287347385797804794857836116811924010708961974681986292254606032206395063078084914269784406515838470630661815491494131433294315539716816235075321043172426359604190553194680349081899881349781292681592947150484479953308226592623497942686469645528859573877582667773589125094536868989582670938988180517648651804299940377660929140216502528356763729908955619175263914134265555112688605429477642841630156830963107723017458158888251244023568765159476285691090207049628622382509975046458160656252318489112347132674239002207165966567317423315430824905321954352762173443168862079668409413962898856123401984237887467216797, + "LambdaN": 10801765143673692898902397428918058405962005354480987340993146127303016103197531539042457134892203257919235315330907745747065716647157769858408117537660521586213179802095276597340174540949940674890646340796473575242239976654113296311748971343234822764429786938791333886794562547268434494791335469494090258824178810215434528734334091930829344169279713171985945407878163029728406174586092839182982973461535281756600746784460230050828255543704021558198665413105958425266218031593229066401673205486037073775269035689031504630542318836427253206102915949310258760888211773960755328329741319894694104469543289481794908822318, + "PhiN": 21603530287347385797804794857836116811924010708961974681986292254606032206395063078084914269784406515838470630661815491494131433294315539716816235075321043172426359604190553194680349081899881349781292681592947150484479953308226592623497942686469645528859573877582667773589125094536868989582670938988180517648357620430869057468668183861658688338559426343971890815756326059456812349172185678365965946923070563513201493568920460101656511087408043116397330826211916850532436063186458132803346410972074147550538071378063009261084637672854506412205831898620517521776423547921510656659482639789388208939086578963589817644636, + "P": 152793418385986211194606641208820856394736985868073314062376223335453727103296428127935717078405293105881468615082916405418508338319570512028274502222517184419247450554336199169797723706951580371992763565882661345243377592705990508250672391129486212134698734843306676137210677289443117643840571577343312356039, + "Q": 141390450685333981066349713635019161809566579115655045445211851473289036413123322983741177628680974344024760833454782381176224597841151531050680362655773014676938868769180714485016521573292761189816297730293331600837951301756926394974320615571950618851051160404044746871716096884067529540474833696954337216123 + }, + "NTildei": 24280215189850071363732442969893473149533654640543993037419498264798829315861184016029621994684532110632770714560305133074140324779563316088766891492363287225368101347524216156367414666580970535658630901693213395876252523760380814972732910793922766433073316164096905128099825469033099848582124568914000479759799233883707042295229692419583332246124254170248864338315962011455644883846989713761421678251973024708146493617012317170145440645107944080316369336904606702029327874454441085567150865188683236460941137145895474798971826634508600380554895808794641544663523287478817596548099911478298867080564689794833630238649, + "H1i": 9007705317203282306813537888273913658790786260563680463357025650880667076157061544017632072991742635705517702837085699421252050831934233847941646382941769042124751444440200435482490054189032389049391842304482103068717938133493187672442782997357021304454328238492348592669173053317861253291241335099983642473803416704023594953917657968287828895489320408127265881173389713126214495220707106858992481428720389035780537618465868291980464053661422559133490256400088702259166122932444729353335671745747709476607763231380618116626942845798416315747127706781921588045276819468700444715187938079207465641768227341451618973175, + "H2i": 10018925495728749835032133500132969085996214793897478788869524692480971069987118885943699073297366550591751702178264784559084465269631722814454632385108659530970036742364474021716039299345441695477015603133457163661165486191673380805724436021092533260955902834444439897356688899064904827041197573197462340804507378181634974418478707084663057013069718449320872408196414152712179124795348267920449137377601025562878983185800101190680313815602372122409942356655748422431414065664884893248145594412364785581500708112476455973562052013210640237456175622746294070225729579703558302734731179304953968819590147754368499046269, + "Alpha": 8533587849824646882485550002778139810131456591112273634209552440840696849288754856566001937694455935441386474230853894386781044505341834136390769541172112862228107487497014227910850960408902848311968996693735314745112964554161958230286726675024630317834262373306157820192932707152556488428609316895227723008096534541728456563147280140043513537732240714985868385301263763736227417675746416217581695942103832923238982995865486029362365636636939122381002238308958214159125810776260488651660903669334940772373415567342699594825864867047623901615433347440539766335669534882499790340445223015076392464633405697719139706866, + "Beta": 5285044657092695822612417191867227939332028528472245099628244280607194974430695470625539874433342659183246121785319149258216190552049011593528877911887692315744937271823734817912268909093070908503655957246015020775010324764210217537074575500614208923729054859157762753076741991668329894998107945436271746250000364585237817704585629372508998752946740077801560650607026568533384360307527737035787010425614112860224616896616840024803235072305486967570795864550268051789726833679116590455203817417561489475313811291802029258836847342025082721696106248028961297346415507887253086534021307867513020044374348322290220248131, + "P": 71895168506759145745930019704233012497237810169818454575734310215676425599145027286500685575788815411949310830625666315745849129153568747564627757399135978804182195113289752730484094736150841202126250382155613278595153782825533699023641268910984808024384835829734067105224625780425469460722506804142584907291, + "Q": 84429231108789297331600176759701539867920319577881747911081546698259061725043078225772751058326727123314378341576409123774007681314560047557404139447367814406503722904576254648234339075317375652250944512273575171106105525029174603349427669099490784109940345031009794437092983997714515430055437394806547870151 + }, + { + "PaillierSK": { + "N": 26679746203376142677189183939355438985552579038739605620284326252444444356779104986355709587389257322851634963919828093483236080109705859094847532214789215244221326742210657828130096720762360726755570895241728713125547657981476653500220234159784462493060833529738523438624517012847426207766261509978099930577889958962848916786126489836548796112193239981829203502530108500952227217075100834971293766643332548844178440204902920273995947413135797499716873190013238825119433713393453401041678676605651013194869899531513258196966904895665857559254656126634484138551272428558052991877377950855878747245512919870101444237721, + "LambdaN": 13339873101688071338594591969677719492776289519369802810142163126222222178389552493177854793694628661425817481959914046741618040054852929547423766107394607622110663371105328914065048360381180363377785447620864356562773828990738326750110117079892231246530416764869261719312258506423713103883130754989049965288781487918937908293846331039633333468026613252013983363243366766798308598433974650133170685387530224898847392620519218116307861949140487872205737664083241574261335592601890469522071803272323455546828344611667028090024678088411780417091374825377812320831596847282003366280421743512117430290162335618825041814106, + "PhiN": 26679746203376142677189183939355438985552579038739605620284326252444444356779104986355709587389257322851634963919828093483236080109705859094847532214789215244221326742210657828130096720762360726755570895241728713125547657981476653500220234159784462493060833529738523438624517012847426207766261509978099930577562975837875816587692662079266666936053226504027966726486733533596617196867949300266341370775060449797694785241038436232615723898280975744411475328166483148522671185203780939044143606544646911093656689223334056180049356176823560834182749650755624641663193694564006732560843487024234860580324671237650083628212, + "P": 156438563059542254634590142964685511064824152926905642678372423190484840622616774973757608929029941470170213611754161541336609192374104717935866113008958361214690318953876923050636635100568538466896644548352454188494472014808451846270392660698481095207045182112380394591388893171979311249377005673399485772207, + "Q": 170544561913557943799237614317443665075189324874331133365002544165125179584534759731194786939242157576313441352110322500043614322480717037369531748837797315382072209235795538946898434960435563634316565759826747828423076704033844878801513815180378401681033551881665864725145570659664575415811242959051874837303 + }, + "NTildei": 24895138974448941937024853210531763456462828890564049534019635443059125347722550654978030580579892363944633659695442302314092068768238783109304237532459621062213180415653364364321841253104579614893248233456050582250348799433620978658768957274703353520466950534256661259007497367190077831840417624315799058989046938507685357886896885866600662802385578611011751858246917442495462402934714334228075270506234034699272402291208442007227657781817951754149602403826153614658458972540612931574559655547569867664354685784485931046176167121404819408786767285333538123496380672380549823053628999612844450141054219762278621615621, + "H1i": 19102933504264759760777640707421474865294029226840523131481229925336893049795447790488853939024371728910727704259657013279783225772467846849639657760423038789255430963139847073694682924764148155735049442830659429232152750646748738329071834472416748912608003782310765152136964701994801833335660316140832874020011561643433249597845168089461170583352223509205854046936136817629900002806542568501388549596605586341538149563609279101557932868769001857305751119927881102522859900680576180662199916986039040536091631073334889139402568804109467995712235364363634031506398223563446517000728330488102598261020974367628091663644, + "H2i": 2136268006164179473637974840237784865711312948939168565624270289306317677272332894037883869132132884099295054146958694001629038995521922245054741844021893828618426144521232872586694951397711655784738939258376522514433761747378317841097952927719935062645570200471031293887655903573524408986084164256584783111164037671878340168232580586721347809230287490303782297656198886246279977197890638335952941941937586930940966249993979774561077266815413133244689093854266932483969370294540299854136018292551974159545209667801040375622495683903775156536016982062386561257373387154498235287221776891433904204214286436493113832227, + "Alpha": 21685954814990295600866667829478146257999652196166827274670568914124343017165670887558194456470092155633084929698610124848865767387523811360505792494290212299756153192942528193474509488699901312908823998273538675067750889354392013015284035329184430930572856943518513706849220940822269431467488044488759543557140145407601993182404205329555355277362951471605810249452303820848719710614381029444796143357570981945862336756734028082903856498368551889401921693243222030246978685924050474734125945825010956024058586901318503616448227600420459600229576218554236032725738699380713417736570846674687215988534239357788411993991, + "Beta": 5358942530499646602648204704950636936417897175516102024712079673127192576249972219142932594244627360013271111274961619805680660623789727288483946226536972216227454524755458983065091057864985592379272825181990788724195005349510718794200361382346402602119705776837623769971103715465752015731788559633936332963812372540885555778551159931485364311734759663970171820005671155939328536345596154848593511179006369555126958031686727650444380365260234084465469303884438196597629656853221308582889632163176990551374300077027878106197020846114619323574871159621820051340771100680277374573013206813847701261353534338128097877714, + "P": 81354150846056564292048932978157053381328676154177935348880152516615577347412663650641785342372041919738737691029143395893110629977164576717406024057306994747092183295451252713220464758545574410136691083363238039999987239150619603174219278694604043676105504672956399128968357432913697022139730802817906487781, + "Q": 76502362557864711982418973716834515283858179726082247970992494288425007509371388458574946685922053126492368376202311751062484525671750128277438754198108843709875549268436870827444233587134188085180658299608087233702714869084763315288418349162864002962060276009213178552179660223993547389322102151561927584183 + }, + { + "PaillierSK": { + "N": 21572668848287101158145582541636973331672819717877640035371543298202001689901989876877718641586847132552102199649323422026358962787993228112328763590391354803527229216743000246742325566153695294637206035710442172686168382444931267238982042058397242579987290226128872882840659421808834473080731573477258048355223010827211900185751832246214354514115639551426066223124956314893799546788218466250073941665048640348335903750985370601215938340089099869055999166634036243491815801994541107482411778913622549843251726578059001931007802601656512716213979241902270680661740061520368419465768639362751202751759499697267627780873, + "LambdaN": 10786334424143550579072791270818486665836409858938820017685771649101000844950994938438859320793423566276051099824661711013179481393996614056164381795195677401763614608371500123371162783076847647318603017855221086343084191222465633619491021029198621289993645113064436441420329710904417236540365786738629024177464390554939856046924076010718433314853414211689822922602265015276277095856284439731100834541042561414977244842951021504691475925428416248857629193458531307856898750890417771316726439627440118331313176323872299321852620715056301922538243725688397806872894251992615052555569568402155500462165253928494789496714, + "PhiN": 21572668848287101158145582541636973331672819717877640035371543298202001689901989876877718641586847132552102199649323422026358962787993228112328763590391354803527229216743000246742325566153695294637206035710442172686168382444931267238982042058397242579987290226128872882840659421808834473080731573477258048354928781109879712093848152021436866629706828423379645845204530030552554191712568879462201669082085122829954489685902043009382951850856832497715258386917062615713797501780835542633452879254880236662626352647744598643705241430112603845076487451376795613745788503985230105111139136804311000924330507856989578993428, + "P": 138741520499166517923486196498423772625111253264149755480293219689982216505498294793691197228416432447804733438856290237585077764957700004393499281161031378496891314476698757735513422945693838575610199664250749538725624389694680346899380487961680147506034421505051417312983409856133469817573284249199441333407, + "Q": 155488196833021573980194028279064111783699874782270622440133064651263138570151291994181075354547085070576680626227037354247908724274567366947241498555942249281126985737006807113445476713048474605015174266063653748576936781849228524238111302563794919409917136030086897041646092702306732009855707591078607454039 + }, + "NTildei": 26429808408504924242561895137236638981809070027641968896647929083627511789161213341870524261930994441165356000545458602857776828182417444773977126411295175492117036973189397230025979307067010540064389545005929320391155060590724678578651450735786963521641592339439707389691979218284857018124860895147617065363223496354117829387221977217835458133630033217468770289155226110187512924716677834605145638796283332657769718384420532163585836406719340272406401786481545311178683942375802129751606594114717696983059251439304876088255513498250348741165449704002382881649756367690168124108773680242340994794312688462544972932757, + "H1i": 15951820064299531652671525954446619618409163661007005131346039943759266429239527166826313224558710563219932581460846154735534725868792084671640881334025249637192613085005922940018003587636267027790279542794013832225917905097944644586665630294069461527292289892577441749411224348040202357737020225911496695267822276749440270543402482189600733341463076683541107121848727641661705176210274892479212204854628528629424448066635890760054740929368768496186709818647181344418167057032882420789206981152094126567237709796794548519360019680928693876125586257869135126865021661635938703633432803077350477441752739970606091167770, + "H2i": 16074877799791379443338339477056432350755356859966335419491716498431209641542784838942903002638305081992505154986778902464663110555148390923382529611074823246298279129161765179292323318121796692381794604623031262028716915293257362828003094389217910296468743217850408242321959087063786951852156664974715020370152232887627026782606787152485054641107371867975633244530285368007060590319238446320251110873634426659147712499111381887644329626092291901791219246022675427964627739342946100922199909937824384923019085227916722261008740056703770592189465215720999844513270424106771007648546744134972291041158075275913534097871, + "Alpha": 5159324875064837568224001764311508354731256271851917853748196921763502023525317375039852531940781081768032260382020812457397142129710419997265444443271024903733148509086556958809698090602094101330641867200480443997545740108277316916870170093896840432205890273344717931282169500142882681627271062194823779826968639838026515674604429681622111676434878652226021404984152005053202945132912730445863916804538649954815122180991025339611310443693590542290688841743239748555660292434616483604583263006095752564169177192836420886430816620476016759983008226621384526182569123843108047535125152563614766097295109043958037582428, + "Beta": 5440222588854811362722663344362045989657163056385789440794283778128016414852466041723455812749903925518475808409863187114924277351529971566222439099448257541284285288925204145269307015184771743877066097840573100506167203444543886202536114596392724528706705731512926669047788819570849519683198397264032788426404847166295210664000466187053855340689031110788551381947015998559419153892520227788191395094189789767154205872083299139170106531675765410280617417911729259103210496276897462591674685088837686966169903053706687123543184167642295856725601494555147769997013498270280479984051151172823774087857560236966669834552, + "P": 87138008043258510150181007813060679583669439022606797582596960871539675782539187536829747454690351970847934636217088606733676149414381168585144374825212431826491351375704844166034636289428993888235380920950362689515872079143669938641749597229747429877753930318438669533560450084088582053868751577387682204169, + "Q": 75827440292714161713174047881077398036441041692540486028640252596426849315740191760501953274854046820087131707203626747726625453016023944675762898549197017706185838603084161326943365880487739063502054706399403438546325888006575716229075627982683975083873833701718082147685775559945089320678487849730265018331 + }, + { + "PaillierSK": { + "N": 24320605472281769611433603846904641410251488082870329796805181846280621973054310695380239575011046076273673589158518085003917544301614854613194107695663974550748738716413864440033269793937642832002983905632009737493349001249852153713267397616331816153662195064591617922985638917417458082495088061563167739194877271128624293813870394977905723137242189386267772648798736287255799299617048063074365527414645670315139639124044370028475949853750198124885857177343637738690096202695849561098027817486612112487051348894015228005293881560927507739325834694573296053410504812744744978932185131947391113982462143737332207673401, + "LambdaN": 12160302736140884805716801923452320705125744041435164898402590923140310986527155347690119787505523038136836794579259042501958772150807427306597053847831987275374369358206932220016634896968821416001491952816004868746674500624926076856633698808165908076831097532295808961492819458708729041247544030781583869597282564129577271324142604321102367448217654920482230105525889740288516330460112071523049854644158399031816804627532239556561675567006563974816254181985204871223221254132754956502427490743733688942232191830701403586610327969071081929645172472486745276852898945554093242049152892867458639622727180587603215165306, + "PhiN": 24320605472281769611433603846904641410251488082870329796805181846280621973054310695380239575011046076273673589158518085003917544301614854613194107695663974550748738716413864440033269793937642832002983905632009737493349001249852153713267397616331816153662195064591617922985638917417458082495088061563167739194565128259154542648285208642204734896435309840964460211051779480577032660920224143046099709288316798063633609255064479113123351134013127949632508363970409742446442508265509913004854981487467377884464383661402807173220655938142163859290344944973490553705797891108186484098305785734917279245454361175206430330612, + "P": 149932439057994960924305064740211283375084614385842245375029295908366973180270089566395000818853944672450390526483409792202916192694698598260881329388501065295716088315334028787022088771630906918321143206655008419066297797057113637987604114102260906768089389155326731620757322996711115507495430643750945733327, + "Q": 162210430411756204660881270960776957431794930917470192371927510770399665516553830461870817307474927579055639342496481123149682527042371576992467483984726930947937606115005619306150747227513827684265822025957412413006927825728230242047885635497544592936617532481231763213122023215762719229512351918374831609463 + }, + "NTildei": 20421737019311687924562999106255570986318890649934053490153202198211865081159811246800883282987974662848178581319277848263051121977439029573861598624387410326336158432507787395926178703585484381170622357490225439796982051607655131061529532254596777981970254409940494147054860995369370317962263581663938906981789998446225581684462254892810215261711047986307756386623581321127985497814042224466667134606325876740093698403773950878656141043168046918076024722364243348097139312979779653235819776619444385849067012152519377070773434128503176174985969630008212981035761023231748967463304062846950149758844159789331091496853, + "H1i": 10835174848260754098810788937620020798873941388272952131390693269784935850924042428232413169064458938634900009775545221949373070639614170733138662414647192893455325845731726323633631040975422150137628104818066775037822957989833723939300105084023704856532088347132947745384637305211715546182094954966468900998119693477342823214414022291895545763250190731881219681960112265962366101223668032245836759830440528089502455217342288694333473814533422766650317352462617254440440171428586374644600791690496352440286377597734587762838369971728588975473564478914545786569309183886142821856175716217906458612166270976044159947714, + "H2i": 2208437006578861715644555917731149116444276764276141455903371385382430825238652402193233708915610203385047683888719770218409057177232122806639481503289933074608699281831900233975230585785930475955110984026391385041278047601003638455598076264335693536898972276981763680198133707849190802188990380484756762279849048871903633368998043714537385191129881226827500726553354345066046510159079189994452850503266123277634416949510810022509833555330165147833856617800460889011847166283508758899274161605199335334285567918184413066920856009966220610877572639403259893423875848171431199424188401959285740905363534752429074732627, + "Alpha": 1215647205092419098929888575985101595804324977833712103150226387163796354257933615560027705108175137987437993851946030600332740335762579017947945156270755422640946657288641755403861106914882568372871325293394028178410543391694258555846271236947673517154947085603741983390319453808484289997677711556557801026569496666139001758817832915923299672590168661704128371719554454363120447492672095539162284893403531977139629183340241690062160913496368519518627194598552803140599268848091355955899335310996928924340628274508481889468254564933634004969413058125825001465259529036159247415648431503736935688132383025774570259598, + "Beta": 4181053269301689083053944851677419915490476058226968572970333178437894866066239189905225132920421895096236002351182034986152724795315880838835087124156308163412237000269835562973609250885730266411204676629533599226074240814119986578194380500286932084393073422326001977710937639439856289414413588252890611289074412517957844902241527489843772839180880514870780248109464555397213225554749907832196404755266154183598714362342546366560923854834022637912764215233730248007046756811238484195294351279848848646070197358116144676921194611906081081499913815182421592924500587702249436797289796286536617145021123621073235989912, + "P": 73499865680965885339689998922063130692240345179070407326141453955707094343217980206881447911503666177241608913179657075075107416373167796975678038937231839840420445192982172026191738050982539194943138971429287525203030853085572687274758193655791992049864868234703627563328679375922927127499951164366098090803, + "Q": 69461817481253794720776750264645760351536844356812043398624164012103508157664020913530488107697386851747959292005405964197889610837544618586097173032902804027948721720298528468558595198023910401263444093810431679674656807368422314344618268129201118987051008619101144394243496262415829988484541454178303287889 + }, + { + "PaillierSK": { + "N": 22989021704313753198585575790518742216459767102449646109057501184678871593295290493476311413439256513650443915105020001375731006640997294611154042698792519502288888028344433954515370744561086030989667473748685420868118226307189243117558723706712789210737831835103210111650218368550882414313314921922988791930316071081455020693990545050236488789709813326855357767959643562802425623144631305243158037573670908045735598672518942740521468889060714829856970741297932849647247963105055610506429430126060236101033802242530846582215523130240726305208334547534367355695104159217910252226949335967314185733529832335582327360513, + "LambdaN": 11494510852156876599292787895259371108229883551224823054528750592339435796647645246738155706719628256825221957552510000687865503320498647305577021349396259751144444014172216977257685372280543015494833736874342710434059113153594621558779361853356394605368915917551605055825109184275441207156657460961494395965006139688140338151960839213035219596046044526892881080523500274133120559775379760203237402842413544322271102640317237711171852463423652424773173932153967665857249381310309560874651439374390782418664761592801664534799395624638618533269020619295250773574420644326078789816855979528296224185718750224972501683714, + "PhiN": 22989021704313753198585575790518742216459767102449646109057501184678871593295290493476311413439256513650443915105020001375731006640997294611154042698792519502288888028344433954515370744561086030989667473748685420868118226307189243117558723706712789210737831835103210111650218368550882414313314921922988791930012279376280676303921678426070439192092089053785762161047000548266241119550759520406474805684827088644542205280634475422343704926847304849546347864307935331714498762620619121749302878748781564837329523185603329069598791249277237066538041238590501547148841288652157579633711959056592448371437500449945003367428, + "P": 142767417405269832579753188025181284829569054099127393401235641382431194837410381034088699025319690021008624829461731900422413077474110151349874318624467085201940211844436150416855952664598758342126199057309767928073345083833535733116208863862999306030955982356536765924457768755801417253293401159735920927199, + "Q": 161024287769074557489113436140868312788155218970468213511407373153753308756461403802594532863524129380184768562422735417755350884739299828960748558365530432730808988640000338340270598712679912921578079999617749584543386797129953505554084445080866502515306888209215906668779608154920320108798930725901403065887 + }, + "NTildei": 25455578012420121892151731752422772822935400925431363059998387771486286742736814838632932392888651254492034935457440432546282195520483791367270699683777274182424175582995274974920081833168732880809659857274830175421620074360608383488175867565471702757374369110310377589604602563430163524113760933198210022677840368106527071350200491231903635507136989477129549748224914364315074184746721892904640140193483533644542140128031546379957845320802557877307133347327099493769462832767926217368716468615578045658824439683780194987496356236589807164003365736731383370570473416302294510756595212212599613030462794281448139847601, + "H1i": 21125416144048993901608261117681927481355894391887540526441486268517465289362222892244305634499517277762483240237882465840520543311294784862164570259549295701663297371732120229860798993800793078785148872218908014099322020656888057147660748001948789973708107438421182474635563003503220652401802239810140693325438527982489845521148537155767550112328110034045164953610299493388001930589053125325790167356976310066760061816937161070977340525990900060778035351145441723732327110379364720361174440092423248772196897120598048018763248922905251454903543452096890459662795037802836282296982146389516880783723216127927056569944, + "H2i": 6439712327666121189240108004711515513379462031584792446129400446609440719472440049384297483035972842472082600694783067238133110198600582143589541058317516843936851310064206707174731971615401943686943763278388551011639976921427155854746077516909116011581605790433318056781525741446175632143657896880397028935820822552125204682151881996540575320782271954899885157490924329104974047676715783845749724106417485864572548380093731083005138487777139566605246984225092149251428740187788215037817450586032919294731522570525105515996937542886524801995233119080878693107170668636558109313565539463794090788646202097965568162335, + "Alpha": 1133943921642247826006085839854457324591086337148893131584778667719595815107560518824349657064129333282913010457587609357941089343050805506400138416944205869196971680687756678490713693656891003753754587246786950166124734750665524652910716568075088871526150389884361051671031986325065798283092972318782451927249559667911148873859554538314673972349502656110196949175715737915644352672304835060390591203539194284435969786708921390519874445812386663935450606927794475030882458716676541753745232356361494653422863637585768262732681967984278929104531315318212016115540900090687354736596291639550750922868042422099227298680, + "Beta": 2546355845821646154498440265375548796625753802194766361291306366929711703516137113030937110055955301624367538014275808978632440032565152358870758553837133827622875261355801244996361719525366603074351298525124517469688865374208852140609613031062012218533912513388750584453216347591334153809640136400795290584691398853608526159057855683617609477368373245361878906383207271096505847267564332498407901903884298961371714169775784102739545128128782417685303699240675621217358099548825295476742462889126253078050289800870728043417181317391379285329446713022600038813681800045417183487486583753288767555722094257133704521111, + "P": 75325992374511156988901460493633890861312724852536863840490059790519850160742135705450798151441947149346715847647616280074939189725175266154531725486663213798965397021993378833384202981373847204524798439164142531068778618875797798148047486257961413284209277722450700573497570860077421476493304710400764264251, + "Q": 84484708431912381191507284891311658594298096873211560902503873039529419725912089275989696228584226093034456553477516755804519755041912489274012153798395852780484271673357375121187150961656135619549522026885520858176120368514699118724790947261862749862464179053441972409220390761072616317037661873903915564683 + }, + { + "PaillierSK": { + "N": 22754629070822011612222078234427438670131467808775422391686470372466238191581206451852665393981521451875764084606438340653504569288580225664805298159930024693666750358739643437944394984526459908547595528760542768964821607665126990306727290554569902186140108619476298469347035086186888494985516971414934300650548163810044849659571636088334275463859876683306435561469652669542662668396311683940397055690832249865433617740313393003934616549702114319838322197313183959925164707394608797327376173247397032057166586936616253734114999060395769193766715266881872283032166594496830560248076420985154898994353923643569589086717, + "LambdaN": 11377314535411005806111039117213719335065733904387711195843235186233119095790603225926332696990760725937882042303219170326752284644290112832402649079965012346833375179369821718972197492263229954273797764380271384482410803832563495153363645277284951093070054309738149234673517543093444247492758485707467150325122749810942010073922069832514183466159038850972689725410136459155068542973551767311841979802315065045983185097617317805442571451777109765405834139364351288168364616669897547921297526144649970080306343465417673408348914676428965311731001666131568835203683234720700774947994486278028298917842426357382397173198, + "PhiN": 22754629070822011612222078234427438670131467808775422391686470372466238191581206451852665393981521451875764084606438340653504569288580225664805298159930024693666750358739643437944394984526459908547595528760542768964821607665126990306727290554569902186140108619476298469347035086186888494985516971414934300650245499621884020147844139665028366932318077701945379450820272918310137085947103534623683959604630130091966370195234635610885142903554219530811668278728702576336729233339795095842595052289299940160612686930835346816697829352857930623462003332263137670407366469441401549895988972556056597835684852714764794346396, + "P": 163447110710262656364072275522379086364019405419288319113380067235431912322680877479423110989933295898519152734334528150229459590214547594194930919058935620004920764971684902020574823909089468517720758250883980451317461822161998107927157747487670612144016013797813672466485807020916610070252129127925881567463, + "Q": 139217077450566855363424147783529445177779575941767791535999683997093670126527271837289985096268823874948094810744229242820014055933347194831722999525545763583514709083128799464206297049007623378833141754896926466099707885375840462377554187131064000480784111257615337885601641408181691088416941800878913172859 + }, + "NTildei": 24212016860952068738232580148891689710938323592713032850405089317731343407062889860062556553644041814175446139608628927086150634004666190165252432002440566310643980739173110959658938635246077085679172913531939428582390635518231387962847771838658090425285548587808009292218614367544020167667490090207522345272109053583812225552099614495400895998084199506865536057677184609103879032896568659540567712558935257015851259803002072945262011197715116274821239093183228854656326075295543379128468015577639295306246474222876859345146386944049307151586018026170221375026079899988239453498641070390284989917349139219479049679449, + "H1i": 18835078133089511643275514741897102560928951557285500132299210009068856219094024472374618722095847009275719680129048136196708456763848645464142142715010118589280792369140841347247526992290284170004086359126321955739308218299744612714719436273839667031176604793391576441207185534296291156162701077937009023234792316227173328757636108774090919368351127221387769631882138183413905969140333310820701968097184229597119806927188223719736611622465224115857973242447170574127363054438536760453689194702044284734764458848840453024390037780432121999118672575225267526668296974075429698520770298065792479313200649151018117468377, + "H2i": 19059418639885939279109023123884271431035352619382370427896333779593238652718262795568180733426382512711676933735936618603780627580965955898765878947203964462029159808059298688558386556679548352487079931785912229503224621665831953479255408425470171466756610857464742494360055177614082398174912079960065638346335706928958288942294704231997367797233232542314508872198412167022706779255687042433237745812872220899286057396155509155812584682728145964224008156726119866907215850155327391868129041815747163907321378809120548219730885878035131137377807526712985989541024310357717513076977295921457236049738131547852292685206, + "Alpha": 10852883841286464477234471641772611657408864168144866809424936259492924123398601995235825209313951594796493997233732273882988703035467050097303374145932895584465033436886174330910194378209635565449515850955898892782305965935181438422885873665680117906055708413747658005313519981065162127633952502466517395228078120768780417376493967739233262663252931914777746653674132815391000494340965671491959413616451573072632502183329232874128067102739786712670732351023901591535738288379480089810643162758931062059736118676818478634803277037550369053383692550792837725943295416583515055992174947169784667954094924153737358292143, + "Beta": 1848435642927991624575960399102195436516422633410682671294481087256066872395036790601022803280452863005250330182204483408987401975681199760261362777935601986265281169377280396470738752800317171723856294908215792624872967744372727300569201296638059322575270594573282733984926837303859316286456880987892365104038859425724681256740897154257819396177284945028137407939485918121889790716603034167131150465400827482275151065383996148689762149267231031789574962128076503594024112715762863034332192627664356187953472876461588648132108984382419818857879510602959946444665893463028073657926430057606832691751667361910590185445, + "P": 81042712641138931161558332225575640876887390821193417815048618388738608622660523347143105818385260006777509808992305027105160546060102989270960656868661965558352383836684036217922511152602313127744456311235062323236105131729628054297827856511885907457828501956199714990414946426919558465283948995090262276321, + "Q": 74689062322494237330744461229467209318530704853791196948947734088213516650955254866060698657886287869336005769075766703435129709763492495651679064334320159319368638579197300101673300113718504724312704810031928379105207270825082211622211651831738683824327972341081534959994382312211621930139210184282300655321 + }, + { + "PaillierSK": { + "N": 26643439123479632153282966082259408300548513630660220251562847673995772433179598167426625342798389502621365385580546994137620872339782337511817072851443761730932724619144269140453974594748883454079912671475711435649520918588334167807177767805129346066085772112285840572882293669271770702689253775937002206714480873854618206029074545983685724045624709493757650421870034079267871563376068883797230766888475672868957267869465753375695459637681640030451503622222194147801789092491654944074902728627305857273027236981933533680784320411316179441932211404464361641371722279358252210398277314994693835396282199286061054370049, + "LambdaN": 13321719561739816076641483041129704150274256815330110125781423836997886216589799083713312671399194751310682692790273497068810436169891168755908536425721880865466362309572134570226987297374441727039956335737855717824760459294167083903588883902564673033042886056142920286441146834635885351344626887968501103357076566230849632885793645588783563746072890158107628209540510788492843412991997889257868741854571055701396230756193681759063920571241468872342299570568112641821657001993345121406098797390841603906782391368311752171661322149629686065401227277438941417000710157201807839229364483577943181744325644604812236901418, + "PhiN": 26643439123479632153282966082259408300548513630660220251562847673995772433179598167426625342798389502621365385580546994137620872339782337511817072851443761730932724619144269140453974594748883454079912671475711435649520918588334167807177767805129346066085772112285840572882293669271770702689253775937002206714153132461699265771587291177567127492145780316215256419081021576985686825983995778515737483709142111402792461512387363518127841142482937744684599141136225283643314003986690242812197594781683207813564782736623504343322644299259372130802454554877882834001420314403615678458728967155886363488651289209624473802836, + "P": 149373592106111709371616386502488113496979543367170062025900835259544670136345132936754877614759186132843669421929437368342800176357456779857363074946226320559580063679589159434808864112832038101845141818972881655777275492505620619501580395162988739390044299004773933621745053747305723719532537970428147344587, + "Q": 178367800812828548115638419616108439981949634175223940763111667022640067255727972344738405564574375333321136935148952489224818318841245505909541406139742543598895024825375541827896269732790611357617312426337147681684400619551186691628176454423490067980257665949862598317803294091501748188098372106008433222627 + }, + "NTildei": 23152833656858422094593381148344995251592470462904634467397971487503490190912493266220003992613917740337402367406520108316868609599269726514358343319706460579661642347009898008497894860868346951239810961306709821819692553244984658614211688204515911796138987206353241559551498977440555223010477170546847438130116168739780201379609753272317349739123318484847724522592742742809816257766529802530668720702505225872742104933658102610270627614908882669184810316168311327915327315031350473604495064750358006675334079959765028084174343865101523898006043701411408119642339984642931750663930492012280435951802815718613985751989, + "H1i": 16414583601690613460939333348427386590334659601942333844752328476820536117795746645622317593885857451321489326948169034594496314081822944130119167166149821217313551640029360393664098343694651334428027745271808002416300625284815818402498710438332192636179345503377112522313423848906739883616112745677164049997965266958835173625565017930222231888067117934026862935859709901013586406034122243264460569024164145190679868128713027623479186511725284442518926715103736361763013399615742858633577003348896380185570323497254467447286781011548208851752855525687819335629574615166402484060843899492467321412519628692125378513800, + "H2i": 2196651795701633388960311361261032814335092960928631832190023260586051238568335788473378820942061184272897486425531616446398665757891927137127839961490623404748099140147407103466916387848827731279027032919526734325519037254620966538251077819740829794875824678898141094244446071344450106136999888855126035154731261521862482574326163332997979366856414205284278695261848425273147415487209241200010004249563759300327975258006548181322546964813850164757308559224616712330318265675365952167760433521462734212561103713038165245876968048006633433744978565839353849042653459755622051752933540742936978512285008653494669967456, + "Alpha": 16111933273734756480890535356135651819114122099158898428663793575169811762796992957036916869828456002167762080259603771642542070667068201794532505639051830849279730274610849629078170832122461965120337259059688943904982629085174213561563893391634282483545966251110829951086815870628489592450099909039090123606863865067619468822030995111276276256174573118067462347710432916392276331431057189563943036195137405320444825223904413079764681179990836298845407712496740479620295451423547888710143863181945058298847385674353006338270236724763804240764870194067238243971765628517199820842740212538366573198835203290848465150855, + "Beta": 66839866677519901108559579832824576970009396743940246066320286980422361932151080599264682037183104367308935234222673103857786902541659200539236624213934650240997807977614596416080898284111833515739458303152357633427024568436637576389690487316745802071454841878124182414740659929713566786479438634579292619834869779941893599092155541059639337636208010023589496209733508241250032676773562696683566834941207434334486406318236470419900108803642138092645739716075515524578702433359175652547964873252072472637547359357615556958505644456373318948184282337903294645531444665075790145724279053289577845464103242444769747951, + "P": 80363931290177441667649437082347847606766334734043036046019756101033424635972143112336159247531640937018625770613890424640540603155141821207077214154627243275214336717721436007361202699821496151584402102581024249999741852734730648231244077649211516199413903497924911059904064329466711036888291179499255620383, + "Q": 72024953499531883039951954425884773416678632915818834731825468204899689822176694736483620045905199441040553190142503997693119482431190904186046147767966138410301582664619576983722727699977763346752925570538602035026832498498328170423463307680849451752320657244550736035412814845700298393060726678628070860933 + }, + { + "PaillierSK": { + "N": 22282240729664262892171813956805271162601690274871364084556568321704551843326927020335960533823871871169716385088273021035920519673791963714479777124413522062816491922486181253059557356681886267936296173985744057291621036046793267123297599326388536831632114980848917502692064564884339901142924994750753653705238561204194604340345214565110021491214593384774840841812477482694464518124247863972994093851256991062420832454223654091031512641214433789089245470566446547915305437672100528785359804870724392212034510668544247023145036294707101034429550175617082248695037629869800886939165840986969034323684055889717429282769, + "LambdaN": 11141120364832131446085906978402635581300845137435682042278284160852275921663463510167980266911935935584858192544136510517960259836895981857239888562206761031408245961243090626529778678340943133968148086992872028645810518023396633561648799663194268415816057490424458751346032282442169950571462497375376826852469750201022469023443058268747827165000450421464772040487250131383303466471499089283798122074371335665048818977506932697547795990984710528788889109577968868077769116521505772336649160625133806571721922200601151661914986754840329880590681800550679420811986287788299213181522763617385925008261145595810454303898, + "PhiN": 22282240729664262892171813956805271162601690274871364084556568321704551843326927020335960533823871871169716385088273021035920519673791963714479777124413522062816491922486181253059557356681886267936296173985744057291621036046793267123297599326388536831632114980848917502692064564884339901142924994750753653704939500402044938046886116537495654330000900842929544080974500262766606932942998178567596244148742671330097637955013865395095591981969421057577778219155937736155538233043011544673298321250267613143443844401202303323829973509680659761181363601101358841623972575576598426363045527234771850016522291191620908607796, + "P": 158311068244029288772258102876940233275412332466144944825312348995476990956999268099406394278497384142118921875152133139287093832348591595126723918127915097090191803646662364724106076289988364418287635440832697625066820127782732442054422506502436019489479159854369679390709299573764574042696781083760038593667, + "Q": 140749733905637004686839924737426927938280209379151816012664870932380594224250417305991455424016935590204272624057655556648826826896421136384743333282593714669575400982426619387955407330468414650303030826509246074248242657243708831193764068013287387581585894438832781185411014178432610264464983614336482081307 + }, + "NTildei": 22686046079360374772425847141811858477694860187748404768655134683871478564221840951138421057336329934236440175527384668097337381930560598071408699025274380904121194214281970688330819588951066109639700076933481173511566389051861587982791783345496754142910011590892755790188540852000332858054054875900465497405284843210410034066115815882766069314732006638761270712083819205854336024891572999814186077848770590539845381452899993800258854770121203138574038920176926502303427751846712047964548663487191681671329337344832611164890300434619051336527616695831953800191907569108131749478188046575209446970674998593402311733133, + "H1i": 3032445746977801997091590631794153218915479421527547573407350473835481725683321761828303894072911358394480703054833313230213454623576858512814463200748122734093742258603085765024331882374265075032105153190876797152717027547798969824072034304454486490975709888198015514183697906766463941330896692451736856089901448988417945671415104110224322776060860470662806660862276974527355181407924396447831696297120941927208421663697923063366128198016477664262955351499774132943725953025458686238813807920178465740519711375432307320236739858584247405425619359686800794007766011286982727363623688690883967985618377873810636847670, + "H2i": 2755978893576726203740703932262797966214200089223549312387143843411846236454648811394837242136985649302079153738340766270711613106445136281850975135125954029484765558230774721191328757803756789820873111123075215870542424078927570901634386023470029125006798419653122659471895367906131715147518666300627069993361333347711478928507164367578604883317428762893344561853543028963960483488700310660130915135129262422500322975803493672316411786993721922199590483099985433546230805312143193121175571703820148017091653533201540687990668862781722729837684802734401960993012754494810133621398323288080161523636689922231661625768, + "Alpha": 11679176680031893436868688379791459087233873213622899653090714519523041122448577482385168747413919750317502713446788913511906646905541916430749540911430753953207991108189636288162066726568329654183147495972215340379030815559080411390023396089388713752381669954564699053700697462996144818525839482004090744289146449023538764941835003013254961070430372825575383036186402036443850774512469951000440710486227412071358701972457694256931952017749873532602601156109222534668508922407020535537073702836246713319252042584025221598626832619875325198419394708804378297062139238749221663245052529802573672861348125442535435415560, + "Beta": 1179139300656709625961956092400679062060717467687071262209876838493292858637436070524437891111711643564117229734647346780472426266459784873521872945841940119229937747454054628734491927635793198983841217505629473384150363108202368135757445257738007699241099873109101068988553321290253602154361656453124433555235474510790782459123068546811803485565434721101114461487260182485615961282111133351002770968343151648954397260331178933850856733398211920194142017417075510850726233678476261988839462458468185547843776166310690979315686480117508081966634283733188086742655656298270429261588321926959804774422622836126540448267, + "P": 73694564668654671939995701324622812805725107304993639502972290161602285639457422068197024599494062883730834838060982537608808574873641689596318510627168753099986467077998441970613555580248025564063392302672319302944974639999147430208719531844028132970179375617657401743943460890324228064260276403179381903553, + "Q": 76959699067907252429828405720708288211357056569804155267152875475521659990093917017555210916345394396055842042665950696448931705842296810390643187526502042995914043714288539734691789273176186648369730969683765467147610481241669616898866711892018820025881642980442522310206345092232364528828056376446844819159 + }, + { + "PaillierSK": { + "N": 26169182626779587026893614466978534499661901354584226787309951684045005690788422245946867975333666384843915316246662904666672525824149602792078350261721553941716125742011678363144675255821634370666301192510684033682124022497661196073081627692182978927167549372888570954189250186048318779598273257828615684202846391519457386842288544815466793455917618399498907235808595150043602560923971892244855181526319611113158986476156264512040513271224941826577952764166285137595597828617748727745684006027593535083851052839526344845520406454415274433636427200969430286054362121915366096049985231293570275374118005654845516094173, + "LambdaN": 13084591313389793513446807233489267249830950677292113393654975842022502845394211122973433987666833192421957658123331452333336262912074801396039175130860776970858062871005839181572337627910817185333150596255342016841062011248830598036540813846091489463583774686444285477094625093024159389799136628914307842101260903971109745623471447110154002054315392425882457000511839690183055683702795694311038471176877067245874550584769420594927644378898610798623109701065592517972245495992957043236688568410845159161746809392156651363726029522368710668380251419723189065301899907485312142766234710237000779883953643252483097405374, + "PhiN": 26169182626779587026893614466978534499661901354584226787309951684045005690788422245946867975333666384843915316246662904666672525824149602792078350261721553941716125742011678363144675255821634370666301192510684033682124022497661196073081627692182978927167549372888570954189250186048318779598273257828615684202521807942219491246942894220308004108630784851764914001023679380366111367405591388622076942353754134491749101169538841189855288757797221597246219402131185035944490991985914086473377136821690318323493618784313302727452059044737421336760502839446378130603799814970624285532469420474001559767907286504966194810748, + "P": 149274798707388102445618878109855307595585472007317690968743435589389472479599360997970504892312440800808211860965546423471656851821847870730131313530824938527897949830922828627295513787225646364619391482704162009404861985574252109741073755426536817014135355063963261233473109821527553215730818160195137051727, + "Q": 175308778530507492900031717048934039691248075726675543816172334088101721038781142624807734280253035820601673445651876898713567661605872358601602048504275163123208886800911812645011355418677570395738042572508880108663485424103600987134850606096515338436426951880778549284042700998041162390479900989684184231699 + }, + "NTildei": 26949259604320329304536450610818629037843714090474106161232272624441334477725122710279747308282083845237671497115433770058556065216035113947835751858531832855773841494858860915572039513775607871041753790968812818315065006758970906998578389263871239446482752409922085092205074258132236742010618239338080884875833056029005457650575703946180217603996222190365268873638852829016121609412570514466863782511661107800239268182942675878992303640682226185165050551525422094110299777867064329605469068452769542273703687185430854999261934761571651417788069644969259208169608517734791308387713353771110530052267277549019203223941, + "H1i": 12536756446887651491596090711390229470272463249558916862122243258210332546673471236660488920452499947251622360380706194040090438672837940180826597977749177721750097748375761146415833912466924021573745697810554749112831759380543816541007043303490708306251517590037149837013427282403907899595638075905241659955638729952829874840443797738628606820940756245577823163646672925501838954619362138661288287269120299035291256653367442129811040440112470714830956211485951583568877864477602110585225613534678066895184662321175121391670430785071589746201009987140064755442279565021243859091048618653056608103804464465067377270248, + "H2i": 25750301506289877204962684749336755240803024497001762345788575803137291810029494841768181991818291106096192838013545827248578041199471627895689264489042195890641099075408548947039446129273044784081361661342699783714644108493664349418843840285796004851541111149049457743971256343400801367367102162454829614987982546852365687260325400986723037998421928508585304429392557096969423070791611826454356704345406955157097568747857666592403076111662799967040769613818112585834378901758207281306378293098969709540002077955360748966065308437450028412448681326034275669688968187059204236789155871371836728254081079559038986944556, + "Alpha": 18586085099048762751007252806006682904373253921001849829524864308927872723872606437285482010168853097803960721641630804709008873754310992983574778303733159271970163873400715010870696106362068391293313850406313974089602972582856141404362348881400966674998266913176271437153365851487930917918120568550412166786018763041394161341235702906804381550211867649633402175736834257969134228848403629665942440352017626718432094022599655342992409681205914895921516146894467218558206704850364477245215255996207408046463599536481408787552211448580162299600252660422707809666853323070779081270049011256780509384233795292023114922519, + "Beta": 5209369581528126241867316791232480388668366018773612406247211684156638306664057189395970193442504798320082037928350054669302544279707424380296011601071523210150508313799112541034289391521129492965318462802142888302700692779258613317123249355601101497512875664982259311427678917550923522021697848591782330208377826383914949589472413626526849124073083905914961690511264924400260670599146159324948517868090713700311200353791438286686195024975057338066729922712316790458870660936899044854558536855462642506271051463878899557742385020105766326028832595713664599693632390141440537784612176498994006696121737861280247876470, + "P": 80647143368533455317011653231969864907040916381425009439603652705778988682950230302448057733899115454508888988906120334487816385724108388609954537920588383346769887613838713517522725112369922314542340079404071026273644543836816363482287685660019772026498831590441583454636074732219030286549734087404510080233, + "Q": 83540651530489522216160975911164255180726523188155812390115386766394074000134049711997242455530586591261262342010536349535988363041658986736811612673840951866293778609204788158045257473823425428466028750029096943853827876882220496212540018696084664411180555634703488070477285031485893810900618101900293579811 + }, + { + "PaillierSK": { + "N": 25009876275391172469509633242191149153493363553073692173661319616574250019908199579192248141615661023023669726901339045848147417702986634248722301796650347340816823991672876397823102972872593468516037813027297186868589012179244341412683576956036419258289333117937489350089612686417029768622388337540239988718900204049610575535181877373393229039621625594371675219883898826491672804156748627577017652021648065388433355503024011232954920861424846467580181708033582517624828977614367442104333535486954656617817290546173491688333739730396664258480173829257959533195414207785969374824707115147551866592769468322913412727241, + "LambdaN": 12504938137695586234754816621095574576746681776536846086830659808287125009954099789596124070807830511511834863450669522924073708851493317124361150898325173670408411995836438198911551486436296734258018906513648593434294506089622170706341788478018209629144666558968744675044806343208514884311194168770119994359291808246631226896792071063772813214250032305495527141590726384633434319887299901213792771229340795501225377425165379105684755492821680713051057994940772708878071208146517994147700840982012174962363403677619218685166913187148733028006579914673707125488561383450459124936473796045934716751765922771220588831242, + "PhiN": 25009876275391172469509633242191149153493363553073692173661319616574250019908199579192248141615661023023669726901339045848147417702986634248722301796650347340816823991672876397823102972872593468516037813027297186868589012179244341412683576956036419258289333117937489350089612686417029768622388337540239988718583616493262453793584142127545626428500064610991054283181452769266868639774599802427585542458681591002450754850330758211369510985643361426102115989881545417756142416293035988295401681964024349924726807355238437370333826374297466056013159829347414250977122766900918249872947592091869433503531845542441177662484, + "P": 165152636185976356007253845695398056578396088852663336882279939271324829604567049611760574278029561749525554205088881921812622825533970207251302313543844403483385820919348327485587033715418289626995760922703624517726811937671033011211110525295279379772985125450802319551528211776921916946333819654009035033199, + "Q": 151434920162145385590481400152204554543164894527957599820166117953479334777581775537671535284936912636457046447604371099772787050247514834226763404608192696385300740401983126323344819807512017066094722268231429800273101418428165191255903474615265902445306315434248805400231311278760516142903803126463200031559 + }, + "NTildei": 30699304725561606321175739770944216678368797092985078369544750203662834101305740919699109945687198130415221406890523543216681365253775930586732141245365204185913629119546173367629241124594792745356299555085451566594538489937313644659714739547675633242849077027504343956645658326477386334969188328502532819029365196934759402987412369008664595487225978658084102886766514689651088501755084936373227181833216570710861163794686548609016276658570328501813646069912406503961742557593067978922588675800384376939789936661908180357975015432891727231132543748378728823333225801855012709120448937193974986382652791444195859268717, + "H1i": 26732892263886054643076035208516824181371206471173376856950590978351417018730245245886416021941453081434596344355030570002393360961088197913900901297431779132498907140526221095653068263692844212940160582416129574257683157028004951521208316070981908330488477078370243937323405430981489481077301006380234961882096698729363649107680625071578606013746174893575469790061642376713003276796567414868367814899430467338552161415935247223369763332973988977421613066832049049393394209108145646132975662611088692710211335285907682963534373631347277840968331191897368430458793235492714866126192526856713181296878584929814982333180, + "H2i": 11746013878697435333912512532152332469062107786724669220602400938300850242678920855446647513475655856897489209655860517406402429209469208317919117617717473845130502947427956318596433436338762689865214756408593721724917036197970550337642592092060609222244900939134553462924036583549727750716529771372994146545803388408597937289887886365857411876270808031828731963749883864179772977293481061485791212479868888375716667173214814019228594798339244838017070177165348210478049438813646051234571455931581719358474229811563290883681476936393535834215979246342472189094124553002752174118444001644523767848595281954915920779483, + "Alpha": 14251960068243830377671500898379080968932972058859774312358008250869790919910949992077400157751975171772109020532628217261151092849722783350445887943585110005818053754976339718988085961103800100838164091269468247413757706314218512600078807551684380729741902985359536146956912835989414601184182422913066272147899622465062298598032499906335575019390862218428084180069297827140426942582369855575970462198399599119478588454706955765296779582497557592057029360349852866719989855420813875657322393276363863981249850416306357655585703090986573083965963434656765474630178447483109376891458267048798599095338987106948288913327, + "Beta": 6683578767052642633157368682193524788392788407162385346359264300221069257539287767355636154425800676394494796329208228399952394840208374890872348165638825707521405864317740308640008985051065637797815227588725767387081970018692527623664585538141325913670245440233324760937458762050155688843562131639324508325033821077841107527259593533630894430413304308434411222140127048992327027646153580717306977953115555700482629981952362643971173311136408486644567903139401772141063981880464530069290777834213988731875471206998830920121539071942505204041497013939496553416671752597838105144628522781654555342167449611651675610309, + "P": 87463294518541318048993611115764928727997827794804272644216469957492754687930126181751213488236842372390929110515042738809212864985149434110020149831491558806608620920200378937497717788071361853534253957232620124908888520507890670759841402895752370228809753140453122855985892920378613589503501722238001761449, + "Q": 87749109196468896311313026602175193552404816761423289691656838026193845874646109463556261815959884406646355075624202573777922703833196927669333245889036916568572554939517553066584608266262306051304210675966541117267197177377866745392711728439636505593515179501321920488315440929733569543605311023600791320991 + }, + { + "PaillierSK": { + "N": 20866547341033953694275392572293632865809840383215469618160361728895085664031802824962690535007598636319066451712343185305098692574742364528843693393360987380911206480849159440707147150935222458453705136663032198932341373076186038279669580024105494411037682864707592726445613372637589726378393532481968325932055686320718001168160301477721839360301446639333339231396139572926362644196148267417252678839054613511971088220511038694273731058974672791243166521475712303663003734971699775320281063342513345248240923410504952991301709793894029006253653676981461286984577342295253781422991665516386139211795436587244325873521, + "LambdaN": 10433273670516976847137696286146816432904920191607734809080180864447542832015901412481345267503799318159533225856171592652549346287371182264421846696680493690455603240424579720353573575467611229226852568331516099466170686538093019139834790012052747205518841432353796363222806686318794863189196766240984162965883144278997760853455650395877389600881461330980694571485498462693119391961806962880752858849334227152821513240578292972251730236272677709514848730742059379205171898284765840039278884916942352331558475347457429441324265454844567906561467261014770666639556940092271160582112063823806723436565284638098639930066, + "PhiN": 20866547341033953694275392572293632865809840383215469618160361728895085664031802824962690535007598636319066451712343185305098692574742364528843693393360987380911206480849159440707147150935222458453705136663032198932341373076186038279669580024105494411037682864707592726445613372637589726378393532481968325931766288557995521706911300791754779201762922661961389142970996925386238783923613925761505717698668454305643026481156585944503460472545355419029697461484118758410343796569531680078557769833884704663116950694914858882648530909689135813122934522029541333279113880184542321164224127647613446873130569276197279860132, + "P": 136259750709319651218671655397726531661286181512966991295962770674574445086287369607118311813102250122657420608977123734104965807447429127559465760629322794202511903780089120973205509054913737695697554579381209469357546256564910745613720718149292581374571981978534665208304170764078201376210910866720980103447, + "Q": 153138012013159810030329030569333626877237795858983097129179876865549415186246972048628649327283909083670641130377329015665304778981888244654003299362270751050148034622078974268517784453714902889426418136208884639295632627639982447516998436802627372330891480132176795050463367104694490962453956444326065909943 + }, + "NTildei": 24437263448543629147469512102360541416575702271078863490894389494905431190747258113024617795133138535044984402502686357130124162654559662728964260879346099935022622216191309811437984035309680721406649347196075096737782323565547749509644253624239278303153789946870626140992877771019592481075651162754632021710365888624181097199434733334479619428386902269781283712261220790537086076471239599010611616194338447719136240232047880623327662539670984942814217362528919278385510173170476379523783845206208177279923717592898477880804657220495493932655314190185930612601581317421220527926665283026448868954828546508117535955977, + "H1i": 19978149370065487698930160679970775565093844802080906035455695755054858126686734582869848189174704124073125395637641509145756771890801744490500957165784994369263162575253901060763784904508432649109978101926869169100263130940953314263257451308832311272888136679633469932608364493010807458602114030588699127355032348735877196215695645552918141245336927444649997119751016257993235887537871901989459694519824715865722179834765916302519019247962420804463437280867110739750309773753196554934499111409517061278148431159201354908199043075564284931718852196557460538735294799355538332937673780087811856870859719562961550309496, + "H2i": 14611701654718215290135524138262146538503226311079883275240983106787737300244154260263265623990839184674841739919838720516851609368525488879921784011982498251503757573295439372954453767249168529172731534629479884236698647327209524785300136602978448944123205627058964989353810312578130415002514570466668538289974104449242262425606306463159308650490173017209479520302327619497548865534492685440231750827307288296735478688092262831923551522307350379705923765307899844471512352964607542912692688426723477212287578384436683280649965009096434843796912819649081162859620649168576652290928222319317709142091352275469427322388, + "Alpha": 19857985536436906932295572940767146808214777671187264859474481718067924982642749200128684566457993305480034464088437719989616190361740004265709193913846503582856403906495784097166343968623643030847214162338019241601052109788722646761451136808020939669750942608525037832231807306010304726166100475913821646923588903747224051316956458119090135679800064386497389322377827170813741316785926492157934516273489413027515356363646005972826911847484190168210476013082895014389743534292858499232112998790550471901338036076170672170855168021008483441253577426101226386181871030539992227170266493760740762180265118469153128616801, + "Beta": 3259281609081298866231283885862288331380636676132726556522500219327054336976503723880135460378715384573755453520193689631085691340770753847794365311836710850509529027109306535553144954233049354705124012260944611798658990183437805238024265483681678596495071853733574608508150950168778084702918242633546438255605834023967554220304918313515294693132496324662408484290646405652369090656027704946856052417474821548735306949925683633184408304354391799347496455904122833636496151336185684910767006154926165969529931705337293659125381835119207575321482791459280768288205314553790674983649407372985844408682977781383856345429, + "P": 73405196730714583805312306002060954391135746987712705664529758144263790395659354666405739957101798971753551007292589007555966329111951152085709667330414853472625940762132232086111504472869554152036855902213293122024094449898474171964215132307775309842964812314813361480236164159203485566962135366900658445649, + "Q": 83227293628103793390388792145655914803776934165182250253331293011636247967614250251702288608867716937544784481589401933390181327567941847059480132056496965326428905754122752896614180146244768837835588500629735756970834521050069610584435102900845242326265082737527362740067974253153126393105063815474810806961 + }, + { + "PaillierSK": { + "N": 29058536116035590840035097215793433100858437830569017475096429341465325789005312302596210413792167572731356067639741836008936111863270565180775762776678957353167676362055991196009276515568298904229879822853353187210939635779345667883638612031975320525201764810185009478249799183107731750920797940058261814026316142595302301561964541411479308578431238153388584127699241815728976800246176524224820052679677758361877967909453463521930580427532497620440990957614508808853191528050898331380222249167851266580591097910000008528156818790223075689224169067382463635703494829650316482748935978649120939679031474856901017999241, + "LambdaN": 14529268058017795420017548607896716550429218915284508737548214670732662894502656151298105206896083786365678033819870918004468055931635282590387881388339478676583838181027995598004638257784149452114939911426676593605469817889672833941819306015987660262600882405092504739124899591553865875460398970029130907012987400832322529588888357391708421044134354173841836240618846285056136242075302693557108271822148144330763189460122326848099569158683988718549968475689577412366575958280926005951587427899957729790497842274425732438290089380612918799983403239228061528288864084496248312435915427836914702934941866980851350664842, + "PhiN": 29058536116035590840035097215793433100858437830569017475096429341465325789005312302596210413792167572731356067639741836008936111863270565180775762776678957353167676362055991196009276515568298904229879822853353187210939635779345667883638612031975320525201764810185009478249799183107731750920797940058261814025974801664645059177776714783416842088268708347683672481237692570112272484150605387114216543644296288661526378920244653696199138317367977437099936951379154824733151916561852011903174855799915459580995684548851464876580178761225837599966806478456123056577728168992496624871830855673829405869883733961702701329684, + "P": 179029389867848567784591081527330929517001843272575171739436104412494975355527450398870267222130406263559301697311849935295192606277275334049670000649903290951044671915191954304697813913666169050597007161760224285056581236925416498854135338538805345777420851925341564124816629670740416311159479931770603241919, + "Q": 162311540789393816403235546535135560645527962432336474722113141204209340740043686711733241813251063436792287291896959890436249503887244849291384005585450693168994939573854365172349579454269637948998406199388319366520058792071821590403227250387535233348345808732478293752288493304551117497988260963427713427639 + }, + "NTildei": 26183625741068080070506887731880989838013763870795553420570344092842078780599086628894692740401300660757182338413073265120775585536033921227362405450203210436817685040619328701975323317166763691449055210198630574031767766538456076787136349178431897746541043722716640927075641875947690017056006033061756754250061567922112775498644622318552339246543646679940766978448827382509359183671539174840687705634599807491481224056602336054969597842970091859588386068161594329280714638939669969937434464259955212408749017205094173338711608642704809981964491523652483956816217178634113802630195620966088677516365096737470061315697, + "H1i": 12597477114990805371912525507948479829998830436820015065000986686667943541375775514099005841258729320435799420273048313276478865380344558638030041744496628799016977479414079891069842614238419902819697275077416886421138568052512057687935778272856002198644771762737155853572047658577704885910659161844502972049200150108419353959762802860320414823076133795278370634293169129208035579941763741751070817767566582461277049821372819238588108366385833127834471584288225382823119522440929317258677779466882155965740174478829552638637000436652877037267078988289924608412763898472499478689427011592150862335882594937991679495631, + "H2i": 20999066908927529982645695227450413384811039639097527644412219116539835024853717087686813762691414067396255647737605945258122494955633184586754988921974736723551434216002627618570738208601818983405979238412527094674180708078886386817171027609079881469370894050556368379062214936148818077433548153636144929398181369958932650024951811309038205934926140640598799452697772162589746631476379599214699246810519121817038089635413629616771306434403475379832129053745137779697320627284530996075153057944101421002039969533003972647916182894067064434594499847804906903893891869277809992624114724679987712676645186602362540737449, + "Alpha": 18529637416204529962070718182282093415772625929752532283853842175684104996705145140892057246620825621805263956705057403006948592936048383497303617858884840290143085317462577540354491320165762630169780714843892251745868163516513853015437863419415923076665995105724460962576699229184510109301349742135237529088903807992369992532442938659329055027698534844719724649196626439619873855133148435949863567887504727541062466719858385422733920582563916743587936706050472616049484711432090052126871872353494883728204421911854704031864101848719029116419086680377391117563464876393887078431763779958961366092321460659893052658448, + "Beta": 1251290389200824284992665576977095268847087515794826936478063491280098544167112271040519562526229071240465563472686990577956341177230727636486953983031557110524104356484860982651532956956576053540693000532072443014347246827022369202736176002291607361306762607763509065811319766145645904452596131406599994962782253735164865953869943640929796475419830123307159193527859924957651816819904879452230795151400812549816384369464459121998882437512571405248250053558642572938292694972209246819902389044083405215906386966363814798964625586827422754568022016143904535533526435604424438929789196985205547167745213150840154373463, + "P": 82035462574735815660441201384947208305524298748158123099426230634569365159977003172928831131245554350778710450956878128698345781676209250894016864612791019801368864458893290999204844100247758865286533950931326735149304144421127755601273008919848622574299771223054804189796052966758966785681076387162591493201, + "Q": 79793618879196040690227421729768399917783456968430805877348178194280303188809926242063864422850876331191069884574591530895346094365724639292617023244006165582137508365656420311245376352929632217645030345647592783643890467415515039945798562479898135157753323525640069524167742441259484654901114033655322970349 + }, + { + "PaillierSK": { + "N": 26195536341062750337246373738519774770193400707926670530036752037530531694878557383341202659769976763521333645778230959226974577857256542207803178903311392758284944476507131797627750745521972469484110714748053611544936503228336843089671915690489471334958717422944244488186756742797524366759157910764102155784207767773627028487258543564269240566850907061831389148392772722776841726293903506788595147838335330244600785585567224710638382369561833372695441582166372657060099961227993621821669630587833826510651195870502901550265727679635380176139454193842453256683376596823164239351681274339524999635947084674974631363437, + "LambdaN": 13097768170531375168623186869259887385096700353963335265018376018765265847439278691670601329884988381760666822889115479613487288928628271103901589451655696379142472238253565898813875372760986234742055357374026805772468251614168421544835957845244735667479358711472122244093378371398762183379578955382051077891941753608701738995041032457361331535654192021522270070165086179652900068545323500996056947224781495694066378044818668044718513119274410068401587415017665945438719431478245519528418683653849800148034184188476976678162939733371837348011144201354858137830444310805950196858610781566204215003070219870168292562158, + "PhiN": 26195536341062750337246373738519774770193400707926670530036752037530531694878557383341202659769976763521333645778230959226974577857256542207803178903311392758284944476507131797627750745521972469484110714748053611544936503228336843089671915690489471334958717422944244488186756742797524366759157910764102155783883507217403477990082064914722663071308384043044540140330172359305800137090647001992113894449562991388132756089637336089437026238548820136803174830035331890877438862956491039056837367307699600296068368376953953356325879466743674696022288402709716275660888621611900393717221563132408430006140439740336585124316, + "P": 171653446677900597264757504248061306221239319721606913170686858391811552113101626100395958205289472038024202819857100667801186285658678328963695975974295015995902330981421689807282744935312311339204943763807555377992056786432402776629559505878348835883258823329770611985767958304204771977306432870173968064339, + "Q": 152607109545649899911721145298516189321283699065242094891913505079230037090154878696085295183482866818443826676072787953400169845354334906928570776156745750186758767290080892957549518344821914875377883729741392815947791426459302703487606285254388145139229151881493233648691752902911797652500212064464078174783 + }, + "NTildei": 28510211440672556581099691307481564995286559210311210606945886833332657399185772472063164395719059163201290065084870413941639812358605690753059381167945934982772665741513043192008304119191099558597525120657963828054166885952045058656760079341892315168846565702191710766553948040326675206092628379088526809762065111127085728144527673314078313051053630755513922310667308091239346068966904937585217909847385614922844522534473289510551755637895552909758106044169083639849332947292502595759949914522393020668004890553722476421205949196350026825795174204187896600622225022167501809919697890188412059136888031254205129678713, + "H1i": 24068253491801016666536859767972359749052796434069916187097233410099204994045071820574234159847596674156464159258865755219593547081814964499900479078634981874682179555428358715655128053685545560184641403868251753212348689073278109931395236789795539555767246904957125384857775641964547094207472257112431819133443464906311385606760830621891948469101826954386550827210676621953077733852610026854158397782588793754742794721685535158362925558643047388820627724694574784143945814345258007651218425442503326035417747063939204755134036709722200717095771398413161145584184375671802522849297173095801022245787469652296913390997, + "H2i": 3585035209678874314922828004421379749496465876798853115700188460233811634515333079956587826714293735144504890482872147720318944979218935531633759630590704178058430786897921087694046325328700701410094327681516777861197922764434525284941391728865593455517144713810924205781591240866688260730418439812532962863200336928033745397508524882297242691349523983018431575602304789383709616131007820954896275780353929803389901110804769326794711562291658336194233389473459486126407574398166387862879567542322377168943699619578798941273760750399355067140123159034334218305000523508863074230190408545755400293028663357753074404048, + "Alpha": 22414128402314642122535536352187549917906644474967304915458861529204662418060391824765729568447799445792674774222376576126533684771475299945277174715451225458379766604398030236584736984282721052574479517286231070078829295737535668587537534563077209988221713238064036388273468090790860797321866887984748501766338235130228895428143876409397151778734073346278746328937277606509462381180346208278969217055195933992951261225631954163213587796628164987917576287066131932783914623098814682168086876377101931469198869321019075904934827609052557520350734097254766369082956879999422974802550883392830266383998921136987027156719, + "Beta": 2286446406157824816120318076891668328795267880344110059881230772417623088726937483756356512151832671410634962883168016622618886458151165130440870233494600130931759901722279162821680774873928296824201646742391770404723175432851235489016008141334507568430814170551568735680480167613724454105049619068228040085199879578750150520404460324903060586561406407738992330426219358786991308567163275958364499055080552613062923374392671142529976311126720927802618931086723128828222225997756948837777022989379580099240136995761086775608667784901573412791024810181494147491630443826606802291036949234116170353139531693955228326009, + "P": 85753283656550033188371334959807344720288974234136527414296550305477853566687049459961816897296064891830133559693878918172501060359432350433670120874180306176470119834242710095276681086405348196563402871314003020621312248190404681338135102671291202362956000190485751325355398873382721710196275183604933278103, + "Q": 83116967143959859920363713500765368791675662393722822447357334844622206398494215861350920345321574220560491310631285868733494866451888580662244105159883545809187415939878747433186607835935906534211538745737849916803933146202694514626248491430378367105501238718430622759436493497595178437613071024663034668779 + }, + { + "PaillierSK": { + "N": 23829884647402859140729597185051245932689158253811007387849844174004622010895356716824754598632349220106493699741435175799932175213233811749025883647317370284190055835743173357231183716599663999328514153163618536053404851021649597087977087077016737598211273790900469469790876351458122988089355331012866430452992783985757854946578629545676268664737176408199375634195237015452788745227305868242671652743132815521243189726235441588374059441107689503768401200954675385295981046645761348104418267529371410280565994549859995061562691715755535237156065472064759597957239978902667007772753993947421919409367181399668355865801, + "LambdaN": 11914942323701429570364798592525622966344579126905503693924922087002311005447678358412377299316174610053246849870717587899966087606616905874512941823658685142095027917871586678615591858299831999664257076581809268026702425510824798543988543538508368799105636895450234734895438175729061494044677665506433215226341070024266139657802009228454472848191507924644223246991992074187834251090685251223796860724396927312202843615005728812742478806829751188579898021592865313351850634741108693473211421029721376689344992753829136220070157071150466681919952990440340243750259865751235325370356233327141050864064868513111758778946, + "PhiN": 23829884647402859140729597185051245932689158253811007387849844174004622010895356716824754598632349220106493699741435175799932175213233811749025883647317370284190055835743173357231183716599663999328514153163618536053404851021649597087977087077016737598211273790900469469790876351458122988089355331012866430452682140048532279315604018456908945696383015849288446493983984148375668502181370502447593721448793854624405687230011457625484957613659502377159796043185730626703701269482217386946422842059442753378689985507658272440140314142300933363839905980880680487500519731502470650740712466654282101728129737026223517557892, + "P": 138145552038048363430711659597036156145576623838478179705790821242737351822855040309752426499566734866523851884545653575030687720153503112888255608560272081760749095131585167484459688987586875425000454034549374160778961383928332013025759397066794610142755932030022268758703023343766182134588249185813341810787, + "Q": 172498385187527267543899429170286812208583935072450960505462045834382891223080325485325504794772226030313650611678330387858414107294684013720349549208672676831530682031958793673535736482341781476875555007652348460643416189526269860290400094117284500313964315370174088273338503949373635546649195187631496497123 + }, + "NTildei": 27541533673704838139999311692847458506673282681628778994791585699199762181765561665991338138685295867075281320538997529790819839971823132278172989385448250335838936827748250068574517759099395965307778003533033017595135272467841391532926363790931456307765447985982247823714910965275050344120901219425790391431664916069399733063281486261762959210384671479588904984919299673684285653969434902755671321234420999035841857982292966473534071407349155813547840025564354328239096635697767399231097211444575768171899835809370271051072719408066836578284428533412479712098056597439901058409445165075293733185921967233908285369213, + "H1i": 7231349892436693547117938131928997957972738879353676129620369580038354601195403173173393035968224086506027575864433486611555330892969496918025237496366542908427786571694996339808048142356246694585730144734111064740747779870773439548000970054112147236802241526715180427617847101566522944864128879297331485663319080072039235130587950391697925779585996170872368928736790077326730863641137704177319465181219725375452484679794985462225563754752207545774844266282992305913641629821531334895712224133514249145650992309393522034973215297552980363978782151500507787952151880560730987146140512199645162498314383425421709943719, + "H2i": 6487534044907471523394742436170100508831634975835919011991679715797252370271671806619459236407337991364599568817910332380876658143944672072010066891341002817325403687732242758204901101263735092040136427031236902772335051884935897091094982262470268799518251328895253203203723802447545704395282324008257347558371618264295346239340931826031886196860993246286685460840051514324008224747452240508618057600195803569486546909459040696367675226088417362747188750095856438943112942587699287811620866667632191782898908032944736669426681220567873890801914118809912404307170456790172940969140697025483385119888012922410891547033, + "Alpha": 8762634014972522479236447989894139195207707834835173613597703233037993657197028726595046772460857492729877926366579976498082255630558431332623532291766885713059421157908649485174595463224289095440221003973158234871326518182071469618449557515664550019098833996772649286183239578438498053178904337157467146647078672103992631917877586258284347291947069615619523160312040649086038720695359113752934326997413416550925328875695008343338060132070707908165061901521844158606674860988264734058995760607995094687322881869735696757803841236319524945481168411794089206239983555600890103413164617989610349833755314156363536879120, + "Beta": 6383905752428796250277564758113000210088026463420065838839084614515249744542787137335260156352781909285575181736319584584032322351754147212831711180929383657797703998649286915337866579299046232916374090641551070593243825134167908920863869754204640227991611336164050724277862128297962931418130122432222200446221945291378827394238707155652899647837947271118136644970160275460258175813375575503187073781907910436947950248205911933849251714803901520009543233113807905328953743856389608999384311689693859532053392141497847428716570447646055799043425261976758350155390909248843772671309845376700057214591278670203530835688, + "P": 85841834889536335613758447471256281748366882001349032711909262642025101086297091278273453613453520979101708591671269072160274401411097701332213558207622058770553611412922280227318395510587538140292393188100585038959696491926812731586173105698409784742194604325269610587546507554657591959858904662094646986623, + "Q": 80210114651981900436987544812558274321581729109406705575489964703916113750100954586667417016242068531961234687429634231187988175556180229132745950710770303932973635098275903719491664787553760335765636177530712510154719330402270000583787144033715649278677412303588268129650143785925648822433760211871631057089 + }, + { + "PaillierSK": { + "N": 23490601338909561678561832850575558726884812405653943804649911011749816963601846660627582966206308492497621991345760856662153250993301697575609069520647968941908391330219919279323184667316614275866188529073861802049646638752896985413672191675323131194787350502922020356859165571809895487566955513232296714735176566343559334688077288932255710061566111770667210646194738615112742599112692806318650389600040601158453848509908544326118921059747973287595958562847353552628304515249278417520256357758403456529924057003647836144578988214811244547272745251882312872469476813473088985927927771644309809928122929127461230006381, + "LambdaN": 11745300669454780839280916425287779363442406202826971902324955505874908481800923330313791483103154246248810995672880428331076625496650848787804534760323984470954195665109959639661592333658307137933094264536930901024823319376448492706836095837661565597393675251461010178429582785904947743783477756616148357367434164592757026864399688264877878353543799732900488709808940051816925005714501280232262921315235820697818467328252120801771834688123330707557842703818047183347474901127266719388123158296064142821683649396640871679694415397886438009499936854715186866182033421981071082040269129930819853439010532920921711004782, + "PhiN": 23490601338909561678561832850575558726884812405653943804649911011749816963601846660627582966206308492497621991345760856662153250993301697575609069520647968941908391330219919279323184667316614275866188529073861802049646638752896985413672191675323131194787350502922020356859165571809895487566955513232296714734868329185514053728799376529755756707087599465800977419617880103633850011429002560464525842630471641395636934656504241603543669376246661415115685407636094366694949802254533438776246316592128285643367298793281743359388830795772876018999873709430373732364066843962142164080538259861639706878021065841843422009564, + "P": 170302986983647778148084655559799875300219484383294567153445804502839290936092979168068879052117280450963295109324249013673066303141796890373592396982489903666221430970063608585456860242063865477717643262299856089523258586762259268631644364469784961187976103497919172879372340161714143074838128098748170280339, + "Q": 137934171061633181129827746940153479178292820482938659423412706976053296747597266686055667917451679311853618744080053708902185380359514982106680758228769282267133282024681370158553180924211305408839114948066236695666898832276109259641227177982154178917433866013027648968017171620955959975263735186869637716479 + }, + "NTildei": 26409730782654867095866932276274325839232789871545669928528346987651006049118622730214464109045297973572779748976527360110284557202924055176912573769543507304926362966976563133750424601730756543081393390425901904396680491014167862188513832119806530392548104828327143562391244740740905004606310984328163774343843655330975835708194582962677402970697567600039625209441347642245568764561082422207016047998283319718660517400948670666493389547649722125232981527888149651054292955754223313051227994136309544621457084160848169516258114615899084150087908699696648101026128601159872329596004067429719401219808321396819850932861, + "H1i": 25787470845667828439333194128235746212376382370752110453429873473761119213974826992009845048404136469505934227457654230923200229098325447043637656322304711430889303391018095577612569749451202690690580531438678549244568560845872319149294372395531545389913597349014831139184275332411502105630542654628108421654352780938736116879874535886828041477369321010378454057396504028130374837377066223885903343368846821057545084302134584299897880566762947524317852732517573416566636204609456445024093151036087099799914942942374379479912067639594833735819974633785150165678769707286370726404595818135165251634888060035796672078625, + "H2i": 3064350222899130161846345607400999484162450981074121667593094250042985972310366059815035917267068347999069085586208948876186294977267398684913614262592905359878533576599928037577374440401774523722297196822012860279315676763854039744162401550125551803573359185803797750061259561130563222611587757971417639638352837507761156497391312694070108528324759688242771704183109376594315950462945448741984850259996669874710400899548023065244421635195591160059763530777589780515966472912117106023789491423392738068386491492721413406939264764602796271209615587419095527954072943229861144338557555928412226551891144762697588999537, + "Alpha": 25766327008850278931129487555665656864179172158228979148202079684010161542086645287139369308297623212582828296031897710385636903889779911933246523749843594812044299301213991227119289554119063632717487755434824035119559498750343169564264106431068472314741756890604063848869266984633255680820177932313206316336226067095580363312059300391789672506557327259511274280465462561135788335935342049427389720406239555544186908678247156605395963438333402243998336241990134762298536491843926179215953545383439324212248905551461107666898065351771296197196736686327895801546996032875072031184832322819953359377719415579985143944990, + "Beta": 5709342927292575357919244843023247358537095262976597275416722504722701552065098751505138579827657048831082424600875474298313223119121633371294395553574353717644535570811796838298947998473215512359199926955096778997238585849116510337055696837171835460598227182978440938080315011929395331459856375776031108204757988458500238779828499461043184188883099344040141412131978882415628600909699500223857965973599069661364760182148215671697572842537372104150657993249399100755619960250792573721758056683935409489876503054891989021159788452946133516361421364401303833448947448337115531449892834087998423029120832662999010312625, + "P": 78300870956572191058689075678261348919410556484818210995697564106065811670858967319685144742382879876748683915230533871952651154993826160345751439221863208193464655611309253601704320323646111743323854766434008617833234683294660942706917899252449490428025864524999619404773776554939742692648014585281239451511, + "Q": 84321318715925993886343258356475861776534259689989747627307993870398580813263225829448567081510022747430786745931113631084409442376763729088813227276108297962741813610840210995928154407234253397708649733921253111472909413831056337306639599394442988552895885406035110335332393526994524740983602380968600758953 + }, + { + "PaillierSK": { + "N": 26209237752569703091655317506342884781782712735030728843768874386865886608161718448425410431604757037457737778627341881471795375141477764495798577822327640736104808681646912387939045873787307834428432131050366477664601944159976633210398165824296390219671065251790296394799214717641065373066117829846010913709816379658709186644752418684215870019980187340670275482573583690246044241111593119875568761626467599862861012922831949616446494162282665361627601302424714685716143295991962405952895505628778016522242772040696971440775063131779669633069132983190370111442391405678583257488139744594787054307346519404342294503781, + "LambdaN": 13104618876284851545827658753171442390891356367515364421884437193432943304080859224212705215802378518728868889313670940735897687570738882247899288911163820368052404340823456193969522936893653917214216065525183238832300972079988316605199082912148195109835532625895148197399607358820532686533058914923005456854746067990218752217703325330748196571420651835156003661856227917735465098797953061991520386777489565527405580973101538628038527921391131067164147418669899602938500402130729873583256257319958515483533845575179769505708589506975762587336569275469288264024256097196888051809490305478177972656670543522705514917286, + "PhiN": 26209237752569703091655317506342884781782712735030728843768874386865886608161718448425410431604757037457737778627341881471795375141477764495798577822327640736104808681646912387939045873787307834428432131050366477664601944159976633210398165824296390219671065251790296394799214717641065373066117829846010913709492135980437504435406650661496393142841303670312007323712455835470930197595906123983040773554979131054811161946203077256077055842782262134328294837339799205877000804261459747166512514639917030967067691150359539011417179013951525174673138550938576528048512194393776103618980610956355945313341087045411029834572, + "P": 170738855569493609290601569378800377400466394710066957583002595262164358553117416599284949127184825903953526429233685953900427266964553892325366968757887024282079365447882407541235664564967715160822340863297656079610986727723166548710599031795621358939759386057497658926526085743830354383814465523453030760443, + "Q": 153504822702188600055166453340676499738417275648201201278125259512949684962569579293243038944303642904096324547395186406469011052535849334973939496327028455557063126282620251245147326423893270394352740027039776349746897390104977909685395400456172224454119825227309494942633047894600754610190966835478233908767 + }, + "NTildei": 24095647828292496767198123230203710238601231234383057977171740906284364301549696865180642808431559733272431846824384583390062834330776477791699935847416708882943715313539300128670174731572131533021336142206180812283230960878862430102847492273122764038034717128495523172784100444969902386829263433756036489510543080036009167644248158181087577861975298999671640724956622007075187893141025481704214135654884668228901241511500706564990207746569246240976162781762325266669239747300849548165684665695108552403962777497380154080752181244456003031849898998171022371845585436665686617819428961503568237722150521983172953485797, + "H1i": 852985123265249962978889182982965793742691494177745954833146482367651057843298193408855645826577523424749249089862340192136805671536057715749938961466481248882394835333038204203071242097828082238012896048540506894707728963165978612335058415091818361259553904241165288147668268103227084684028128238712250197479500419878928520132896273223113146439632069542231369632592665875406253114150013214790596155706707540360038898709782854232684077130994530035788365294611044464087770024354893300761343245536087583544168014902933283954766756758467066175649294952453311887474017653941772601316673491750157364637009931891843062839, + "H2i": 9395601261634073643688217872555610910758969585471183037453198995699916438919370408804012761775448607876657557361769836834201056472498711208952684837932717287015357766526122762373535213174978933262958640035389584399150426299350450439251536951240078498598864973832628598633894701983361713600346236574466880761271869364953735640426675884285611697640790330381862576890678959102498242551920995495826526116662330536171590166423948196772285548765160488340407762355047477147988392262374139039385394558722827381704045476034708603846097273459866529101282512764108643495686792885532509151405903588165529067595388114432011429326, + "Alpha": 10850631217907308436434645445937044630525069858389046782177542249377101902353918262443234192404918179256375188513864767195126142585778576909967521505600213466802508822530782501895554589235350563514822053712794849940542124785957973392566000300478341614860425502506438376599161683418676678907294360703811189921134325342073995428949998314596942748684529390518261567647426099725090331930781795083828115442527322173099663977764088654534806695486429944557133200435212962217023960182680009626319974673515553562926651620542277882173629991379280025954524303079762516438333051055878989592222682621687117751258420934755837103901, + "Beta": 1172485740683118106955115531144625863022766762541173913222388075235874260034094951926288351792954875819777051517330921605136521476890256440934771995056037714173349836800767099768076383601116213917869671896835221853958963609385683906380113886191296842928680440633130801099521777243327439726737277854368904169336569554615798640751516855616891088264142082305433062461925603618012847791701059553288456629945078393257824320014396986035034516289393998479215916136450810212786044478778595139915533249274138399782093288690550467466914164593337257193301744645610444518250555888339562185033397718066776099484001292834396699583, + "P": 69003338511845184385574753317289313431561762931560122875634935066490390857304235928777770957781530161614401424836399966367683457695521647162692625884858513375032760660343246433139047806653872038018202178023578715695898166506602641554395401827130014435270062806426838827930227291413191271013337611490177776091, + "Q": 87298847954132729985732114912807284818567636386737355324327500427195170474444308862011029692086931598212628286929539803074548281557654168656888476601829996053754803483547507772343178256353082470413953375736476230348967963786816065721808938144347250283279690937942629111841387250608569547918627887168761114529 + }, + { + "PaillierSK": { + "N": 24226495339008659993347335264605591492361432571130276224913595141570778081189757418169593983862931902246010108037808521900080551557729218766501797299247107138754189582404967009951492413969855496198633561000910295527779851700367036095737947890658196801491826514616276578458533152283839906635216412083742234838852478882332936604066612506775290899826099570759229742367439949008871749631294319856462881632450030436827382325392622098581179464152062182169851107008632929735745959264175086727024384555634948214515026203642565075729254502565748559601831613482965022691682024914400325342768604574705412144612256330071688055341, + "LambdaN": 12113247669504329996673667632302795746180716285565138112456797570785389040594878709084796991931465951123005054018904260950040275778864609383250898649623553569377094791202483504975746206984927748099316780500455147763889925850183518047868973945329098400745913257308138289229266576141919953317608206041871117419270312412591412988694873312044419657530849646836186299469056906849922304434914686803467859936484054256682726422281673627074278447211287702645759316656423237958991563920368438001337407726387974266886745609716235669557376235725674961428819090762433479637097303183428012807794896355353172085982803258113738830206, + "PhiN": 24226495339008659993347335264605591492361432571130276224913595141570778081189757418169593983862931902246010108037808521900080551557729218766501797299247107138754189582404967009951492413969855496198633561000910295527779851700367036095737947890658196801491826514616276578458533152283839906635216412083742234838540624825182825977389746624088839315061699293672372598938113813699844608869829373606935719872968108513365452844563347254148556894422575405291518633312846475917983127840736876002674815452775948533773491219432471339114752471451349922857638181524866959274194606366856025615589792710706344171965606516227477660412, + "P": 146613441659293146775406311866447279788346639511334885504405612342338918665379823097221343534242645561654940572609899384060946822956159682342351807999826840732672919225554098198753325056808653501846627616599539444751474705590553386913308470426456628615501881806105118535876468973261670562504471227142794860843, + "Q": 165240615490817479901459570820004304976053637575522257924920522966688222096085123152305818225239276361806988908219375460371675746773327094535980665695959613085089912197884112525596244046050346178894907367610554291863027325523845249830884961531641434801985536741439181191302342890737397410142178586701415534087 + }, + "NTildei": 25646639870508679890457467827413071715305611680538511450942738572900513370375537281008005029244818759114526769098981057864246448497060625789142998903171026415918154547778876374500212834353649228108879675848178485018981837592615396683434126129828330842312369716930461848064453161128273312406445934598680276206473888777771305800683666665940568894751979233943752709262801902571386688652653900966533906840569945191317050676111265205965831176981126944327218097187572812111773841835222556984667079724136501847642556267150880961901625633982612075044245342388706442222026421139421542156808791536401246140747828266357486381933, + "H1i": 1830436522004219017331314396008833883386543254078574250884702882368390128688159663993320379778524310091429422597552391446700590611555198874718640399315324831789427565614116498213012520385437850767917932630146786866088766487366821410129377640358936343641082682056159898777290383981773682141576989313438439961395765911808110618455073303628141564407781690103818441716788813828578637232161407025711185908096246963752275647515205082947758755115661589723489485529989528882928929949307208990629769015580925743267604334519881767887662872116987259307240702697345588420153293967498614454655396144668514307653999590891132314150, + "H2i": 13207038330262414542645488938480233110924622530759856032421051089622789593515992471476084194187392424384717333212503546132258654867413684285694146619471109240434056433360743618818325523423252686198620622113114376313226156095804723893582353183677428207548595961415785390007536598561557824400101057903769185128477599007802277494072327616961568898164563060117896252355405212430784908651167441231028199138729405681467845664258836973473386063851470201072594658403998089596910196853816329104018096129703018133425098307386337589001595373944999686544689970941023605846173579376115700163556162290095518801047259915723246133480, + "Alpha": 4456246080727343671792277776089192884165217414714493283587070524360263018918687012031662992695429290308016846624987633863904243527668063401362990040589235531774928958606358275610193076374692887768025429396104665048952725738551246146109434522126669440242846038104685777060585888509956097597243904637372314745230509875239733719654175016476353674403368099493173180604224403594541561073567353635230596169562854017326624614141554008576812692317458797967618696342624158319998709143582768197868740447440264978660177008082738517641881048240715921465237967229658611823860758708364323089251626136640074418542566534522003069446, + "Beta": 1873985825268880415609691686624015199210214676288990136267875279620036725951059101793188864911049369567531975423934477206384903815414060746059460099029671684885542289740758865268346189219637503164731615815272417995232324913025656175466349456273139313391382026059026465602218644980411325317337632044907163426096368026887401701348965892910792011810196307997464098678390730345329110563573237061679613120511217769424877791778693632658232521993949703528292924494783402861688023653865274945108945543183838935796688581565777412528193016110397424305177286483714118700018805893222621510862401762657367694669149723029172380198, + "P": 80376082392840646211962204387469990649286850137144049250836188487866569065341103410362955675671767029354887273300275272480489039962565787433306495308401546703190763576197113410916579887108352958898522392118600420061491507315575360464122237434331251280743168942302801369947512248839076831982915398602553424869, + "Q": 79770744937405371197297579512199151777730394230753242123597882727715828233153742983746813191939851847791928006265671569542607937008583834939723699278504573195770388469270509135072595109780726995327317547844521727081714086694939775232909182300343383164177805405757849573167158870772942849385301514433540163923 + }, + { + "PaillierSK": { + "N": 23918974428002212145004834784274437495972536084914640126129092691811480581585206314122643314883721276553348818089741280337056176460321079060418289059803069008354728640048717271579876794960629527335497926031496751918432981913766372904853540608342709934687765239222630750039569582792591016090026567381451334634570159571748766256726493508086784400417894888192328412722063510957527662520135139951653119586655476648390967275124038667319073519102246548867729678576788066291872283667516751406322108491579153804548395631616384779462495859858842817696540075122375245044059140008713025404189818821534861125823104625713824043141, + "LambdaN": 11959487214001106072502417392137218747986268042457320063064546345905740290792603157061321657441860638276674409044870640168528088230160539530209144529901534504177364320024358635789938397480314763667748963015748375959216490956883186452426770304171354967343882619611315375019784791396295508045013283690725667317129516285175450969775596210858550139448277385241691022422999516544377224442634163044538936459221008827867358829156927930863071753416910733441820317975670494266896564669304882121654756218239560416032920717570281025157336655525540816557935409392711234439070459360937845091194059971898752625929496630056015692742, + "PhiN": 23918974428002212145004834784274437495972536084914640126129092691811480581585206314122643314883721276553348818089741280337056176460321079060418289059803069008354728640048717271579876794960629527335497926031496751918432981913766372904853540608342709934687765239222630750039569582792591016090026567381451334634259032570350901939551192421717100278896554770483382044845999033088754448885268326089077872918442017655734717658313855861726143506833821466883640635951340988533793129338609764243309512436479120832065841435140562050314673311051081633115870818785422468878140918721875690182388119943797505251858993260112031385484, + "P": 138799601340356479987321324143913412785185464672990270679770318467455928991077304608438152826514941417409439854345319102254393500447142264334450645403062092615791699561804442952844064931804578361948380911982322481966160864579318280323437774323148480913265949076556335986994604015737135541661285676614811125919, + "Q": 172327400057507837187979762225770708736154653035956097196294159401317284643789509254137093841698517575246809762464863703338536511821282817649638397222384985142287454767102544210168531123295454610534173284493500247181661684228442904257231482013804295252652272210280999234807094862000220332302825688986981531739 + }, + "NTildei": 23754586334013640952387347374181481745246111085139419185419994861368042032810333593246633376964318816724870668652914020603769924339705038419167605336493569157344381294056273339895350319521042550819854211936203254314129664733897642669613681075220690148866177561741599102716017351223553688180555905814547270181578596180923287286188767352472875084439736529797297756828312982446565708577305944270409368170062956319750072756943798954125720976144840856558070632009776431717606793446973973943819115567763353578383343100378732233033056952970573721240868194927569916987196067170771575078539998395448652174448398571170766318989, + "H1i": 20234534221346036946661072588421808447889547272782562181768161817816674330339042787336118197200974556405472594808715399150373800925094932045172085150461788805565660516563506937613016504244928818238488104533326795031586086333742954622296202566122804832153822672656398923622383626507883937480607643774924580568059872219489282941205147400585260198980400609426930436288158850185628848578258566091785890633993376539004965583600097173300667312930251872963833292382572515280503756731381437518807696419874480564198131650248127784402348483414493729494592646398659341663140370212266191423703997356242522335537688660246323788834, + "H2i": 1543487835970251752814319925832531789584746055913807831847746127176653505958363242762364214567643544598469389575303437633363276853624664229421088608618586461781714951119370848269743642627998105361450061072775849541344219530408749231962516080815130970938996831111706048554564536714808737807555109586374381885506733482813006696121363696428642263549755244831821625056668962432789375874064992417978559745218177590864899922690473146689891989362255782384315954959575710103488312496486764986627003524782298342060758254518588820140331659589983066038463853556185070966609266484315049306946305755129077322169739283991219454513, + "Alpha": 17274527130641727665923347807645100582638132473233531004150531666835587027211898217029048448909262519853741954787103841286708212881558551721555126335329553509071347820002917070935507660797289158571840989657321477984050150531134041021765838015763531242726610217796890964100872892676171136687302902777554162130266196495512024354066982429679678707682334965154048262452880475560933558048344979800680009178382929744023684708369215509010034817627739801485829241939056666244305350338905873373223386847471500046960947050859442277183337750794252074572841374453393318731599371981146344736669882346111324919693354521733879500964, + "Beta": 3137833192089211057581401968093597481396084628659032103784935377850492113676628237379235911153045946666430041440037706710797110526610943543866363908821842180644198782566298223784674129892897186059986748895188094969053998665388832965351082106893071689839645887093119782427193483009467877266911405027474961758788148409072533679230296572003923326632112965123831881099941998150596545989958767531794510717626888105682164226356250906402051582978665161384485865476507094196497771741622097732013270962861779251534359184418040517411960015229789286074019625054090972850795250123386348363021280708668857968918106500350672704617, + "P": 76901327610600597922138839108045431622357230009493091246261369440015411670962538261781532809418201887232286751935794843216361717620364909304026269695608182117780302748053114960694502604154034321818845870412651587673617181611830814426571453201890040990140510817548563124994578167656840042875069905647215541011, + "Q": 77224240049202832221228211643209478113500562350948543199161941316146347350459134497508963711994731797136402025334635523381772026064116966011214047696701544595573278145466798723708042476555018190439241890347973606957987019422843122009236867464585390053300258553947202877455472256678318299213488652629523952021 + }, + { + "PaillierSK": { + "N": 21304955020407487197411730288024516332391148670740633630846108959950090449906439063431177707713376695132385782707686953292845786673614030007397087853528983150857148884784678163357971556858029401205387205810196163267797965429564998885228919709670085148999076366900098980094182971031950866901525362592314266715792237919251541746120854651386542745836781288092608721270151789661363861997725029514884470002600003775130171622493200260285335970774262777516192836901576030723130345125560124790955550173314446284971990191379609292197298288614426912748030152595873953922589509302246522747073609567280809439723031027005801569401, + "LambdaN": 10652477510203743598705865144012258166195574335370316815423054479975045224953219531715588853856688347566192891353843476646422893336807015003698543926764491575428574442392339081678985778429014700602693602905098081633898982714782499442614459854835042574499538183450049490047091485515975433450762681296157133357749955617204489799709624173432368034066560721407985537306976052656283985058801106708879474875857037396735385668287883405007862989996112606703973145010667846941761813880485896459135926243193697221354475738281662483144815809170450487019601788879230046084013530389181065492469993292188264309578231651690479254266, + "PhiN": 21304955020407487197411730288024516332391148670740633630846108959950090449906439063431177707713376695132385782707686953292845786673614030007397087853528983150857148884784678163357971556858029401205387205810196163267797965429564998885228919709670085148999076366900098980094182971031950866901525362592314266715499911234408979599419248346864736068133121442815971074613952105312567970117602213417758949751714074793470771336575766810015725979992225213407946290021335693883523627760971792918271852486387394442708951476563324966289631618340900974039203577758460092168027060778362130984939986584376528619156463303380958508532, + "P": 138497336462949434754980609815195633167885334632900676133063918088265532530682489158458461512016700284710034193768483110496071582430789100515330820016973279768218992175640159125169608479928067948151689410590962671301659158534290194051285254625200205047040298028201895583400260474769826196544043665737360673703, + "Q": 153829348379612711946625694706611044535774510643736970523135766260530359349440326938667058738869228696949366092148950339773538408351248463592915726863267057071387725188948172747514089206998983894111349304225321654606007511739235744657541320212213656707522150495682496178733362508134454624022524057887482387167 + }, + "NTildei": 22982245201168825265801027867115038738850624494713405600577345100940519763870290021264156653592448755281270328544503708146716897665358459869265443425134551730054630468639601120232242265841746018152367612787208797739252348658989601911603182016148322340688250020724927709096938877004498848897030720402314279351768737535985841295500700690725601247530625659041925892743611140775186762249707218001473105354928405071818578505903291599149266082551363510148703438824396595411113478753127167937994427989838268152902401241426552594614601420195404882223958770915035969780935004777451536507171909879256996786149786387699792519801, + "H1i": 6955497152353002250359002102740982256902749902340450227310885849735211701380443393631760858999637982526455968578781979795728924665117696881899803737222762624390381177648721575837712437637768873582905778929165234562670312697011705574238422076044078265187289143214724927892730926650383258563153336007222470207492798052452570412345098231054830253513930967562615277833667929966897000083806949845719971081665992914333700256618497009997697651736293941371089561356326478492696458994356148904127559268413564988902331468527960387775360060059540115259383237152162080614780729964435291631541725107674475041473387232781414397368, + "H2i": 2991306255351728643978350943234096404629715511963736949875914933599100218586272385807964150583269959219715638036992996250928565417898897913806335593208583289971685346539841735490315920318003182943396102700691126267522208267560710947455072083929328490121927890614258513623271427469375665175966547505034225007665537668919034942471204140378316067717294272041015381365985876056045063031654490183444245257885618654139159000569579788843156893115704797219260727793431161241391246718637962730984598950719594090589204472553813805323763325795823694885986988927036300235821818380005760523928876771771972406157274523499500173674, + "Alpha": 16422702122488996359495461878024150642809238299615607084384523100657023981286592188567723311780072986693591033988875787853467549991328585271793608626245360928267542729440796265699877699865957428214192791764224465779275376952683585001165145440895473330681936259315472462315462981005415247192326397134840720994744155646500104674724246354821301492026576170927487799166246160613694838042775216181370152894467205231370700772815558770844475287635950973334328215557967915891251922007554366229583704385705726996567826915313676746205473242505781788653577619539992331638287643453867477111540557494209922057188618524458886509792, + "Beta": 2448588344039815217454826054648526699934062171006112220824228801687308227250537502711903182951450318270118339187049845780627061872484353382310604948570803355095266158147638107410378947974500743877325222937829651698630191759396663005727649542604222376530390625188154478063607648766849022745643465978956181019745990362443735959099660003866817062707248611178203411298808007694859043654766437525882780061098087564751335270206260420414443944290625760840344334779239221934464973998025721282728213845533834670974408619393485118762634369817143715784153217446622975765916417269363778490226912877413914977617482387250829642267, + "P": 68522028421445552536812060601200567089243588421450422420878134301295078910854763612281877448421731208836837114171214280715582424519721628693422549093443656191459195460648620544230095566565068840857797880004323163119831034333251845064447618333971352465560224315286154376605678828243717201294146302677562253621, + "Q": 83849842636795032631863028359885768423642107836950719731069156668006425957781674027749846000048597323840531389641536854179734592564735794330866953882300657909384279516736642934901545121113944859868708251377520935249164342025756566223360039880257328078431349132069512238961549382456252455783174442482438096853 + }, + { + "PaillierSK": { + "N": 28925787768477618253605695014020982770545644950879718013079950494124484132031704841718558465324188376346892488386924643838475388813361412455250659964534025281746275814845351637483632675592453131287266305822207015673213779900960967093605821330662832469541934036792155453940303767526945604656887202081663633227434101128720211081611225872423904114669857242484076828125988684073059103073017692780866223402895316442639960978120884350855534961522866567268465651365056662395451245210382420049882455284999786466914979171585181620255852792997039927156204664085202603658139314205808401717777421680166752852840773468261605183897, + "LambdaN": 14462893884238809126802847507010491385272822475439859006539975247062242066015852420859279232662094188173446244193462321919237694406680706227625329982267012640873137907422675818741816337796226565643633152911103507836606889950480483546802910665331416234770967018396077726970151883763472802328443601040831816613546819576124646689480681823250650270428285744162443635954360344208998086548481406999974573132711619919055834582839667675474964704686775750986173846589663918416667830476049416374894140902412484581483317518929721093677157688263904536557701649522768188379319116218071142255775242736334240989155428580378255679538, + "PhiN": 28925787768477618253605695014020982770545644950879718013079950494124484132031704841718558465324188376346892488386924643838475388813361412455250659964534025281746275814845351637483632675592453131287266305822207015673213779900960967093605821330662832469541934036792155453940303767526945604656887202081663633227093639152249293378961363646501300540856571488324887271908720688417996173096962813999949146265423239838111669165679335350949929409373551501972347693179327836833335660952098832749788281804824969162966635037859442187354315376527809073115403299045536376758638232436142284511550485472668481978310857160756511359076, + "P": 177497458296176888206990794836262355597197444068839324123101423260509726358636528386023106636912565620058783633114086185476194563946735969035195370819010964379680514301890636297031273564433255278184680407307755566989142982595901792303003454807969481042352154175902001415169327532094394351722003518577022719443, + "Q": 162964518174740814442871431086341218216088310090350232094166572394553203617418350394893970500559510984469508179327462814429410988202579096260922587366717861182435069956392951003062899915741562025763663726417983865912394433873329061737797910231696745857148927593764115791057608675403876522807912788928071105379 + }, + "NTildei": 25786848596901821069035194162714873401124392587673325585014497651541998581117826929020356693671977667152865903241798541951818822942704815371370090700584221388205516149400101312560538786930343283371400431917681908517110150527326699766194643163125698202246035551041420491199641237067016908079358873975369502163721166214290824779234571545754500972471555192117998268130625711826921226459558200530117651933234463364952496208410308227300762490795445268714161656815854122502280191888399970371217690555143096081210920677933020068353854589882497187812533943081549010242009202802203781110688158529163558352250313095880585898161, + "H1i": 4481824439008030008012507578900462323407515443099779471407166575922507170843483551429700361838850886450238066401154774126543897365436550486334599493781256565868790534378858377693813899903811923148129708284486923639631876139705029613470470079257414680379950465128718087346770172090587555687592520015314466851463690728411651966996811568878949937157942979111010824710807095704412003674518766423568887490129884251524036795543218346929888807188896981195213285743632195585405650972888796251526204177799853469035611825950881180374346510279729270752998073965872494723710423855050600871636483892634345413671982895031967042772, + "H2i": 10676122491799239358083190224932125614134027606352121952287297848314481385717632231143812212433535449588794570802549542443899214495951709083917384447000311426036515517192014153063828045286894456633782419232599654886197244224015146499697210240094583706584526256196625994822540240428346132854143049538756610504648428187422570165273994088741723597395128208437952756982304340400097732657734609565404723478698193536700064833974029361975616924636419815933553076472340281668367157462976504557128015617006397602656663603557148993544899300106940493142755620042543902005804845622814546634648829112966684757110152478490321874462, + "Alpha": 21639601886186547851036251166277922230250317619934308539847786418536989910361898115258325624318780460170741122828327187092684456243570050286514542668274556658555708234419221799813867217575782392956343694791602518970389914306777697420822722032967922963373453436593288301669460578706079576771920052221837685792162357503449873428615181077610146568217409025234225657335045380399340796607666973577619938609762085361696213521269564358729771725678235765227672437730932137017277031134355664768448854826001724445780490477040864136728601306479998642378453553022688056025708732421219166425376663874504130276274273893651288649229, + "Beta": 1466397064309221215074093964241184460785969463354538780107121757257648155673227701156246755664329321843632696823825718923808740324525430950143526524505988159673186631468852146884678717685308795100079279280579535167405159243695723832624028259264451012748693789879430785066341430798321063047711726318687041860919110287737323351269310867295449327625028281092420721587949680355576508873697876440621277408862030654149455336361304181833679535089518755331725992934811711425856355754741344858764596125619291947854503356011623130881842679824060094460815548013521984430482449448023091316887647160646480551242205645128433614928, + "P": 75884160780423116549423613602778314657504296130592796384601701901739848855905823643667996416807985184815534251288657237020793887829912704064525260140161827354277888878561194326451938099044497341158008059372494668585566981075404895318252418354730066454509401445164722870851986077420542413879000797451831829483, + "Q": 84954647754220173242370993199805092833000101059279014261333098515999235729072888709864123247571917255378022968894538699926341790526995031727095504316635358627997364974562727508633928334401437628492907671596572645282493298442283902509916449658342352232669753473010325827285365483782797263347666743955736940891 + }, + { + "PaillierSK": { + "N": 27355471664299672215751296660843386229864604474082012247928364065716029774714705303150786005124716072927149690881758538070552780850137759809565668931590472886657906218187539220786848130698976197283515357593162666372262590465802234547279894935626677477280703794240531464680125357862986939005838367528860269857711805763084475141971131465125383880920599075011650686059214600941554092203451531220543322799853722675319674965143449765009772716143015252281445012818894295250306883028905492050269772988233691251943781452049296879944778001629284234672904994336935606504809435113007947705749752843506842464186014130438057083937, + "LambdaN": 13677735832149836107875648330421693114932302237041006123964182032858014887357352651575393002562358036463574845440879269035276390425068879904782834465795236443328953109093769610393424065349488098641757678796581333186131295232901117273639947467813338738640351897120265732340062678931493469502919183764430134928690299643376517353671521709070879693474970609858652556823685710150898371399115814022763214882216650492922985623828362037422824650143288019117764457684850688346969866510472184967284109450099751303220415359870678430592718486098758335230768210865565849865706134794026385862649244300605042122155238627525826171938, + "PhiN": 27355471664299672215751296660843386229864604474082012247928364065716029774714705303150786005124716072927149690881758538070552780850137759809565668931590472886657906218187539220786848130698976197283515357593162666372262590465802234547279894935626677477280703794240531464680125357862986939005838367528860269857380599286753034707343043418141759386949941219717305113647371420301796742798231628045526429764433300985845971247656724074845649300286576038235528915369701376693939733020944369934568218900199502606440830719741356861185436972197516670461536421731131699731412269588052771725298488601210084244310477255051652343876, + "P": 157298972594787349427105175697927342559427189124298032609237304302111568505513853020385132811680804611375856097421082369018732000735396525101960654834681813728119481857401520805597229656264212980634600403742659784247617931325349935916187161132460923000643787995260659511588087624746222581137402178406103524063, + "Q": 173907503736653085200982871285697151411230666170047539802605876337645780899706050154631760223739617078097847620065643321145391415121042688943955442614511104828247668150559601310104324431769975664868350328565280234511723098106417628295181411473342983772753377529694516468863176617550535638738134696980301215999 + }, + "NTildei": 20875854028258839497257832904161780301947943067608984844732547875966784650159031410033074774122365905047211515254762896479588633294619483835977351165875604822412433145113653066343014178645649364084951649360710609037794658021410520537483045272236868098371828009367288100317607075629440144737060950567022831519822032632019682728390714517581088613373573116342122266735499977520707004525286365066448915310900763328817492722503881150358202074441067255135522131332329174384528851020240957474401690580622790933634869973136619801359840489033020978286561578330666923168665281790224003303677411612093760014318684616917849167261, + "H1i": 3274534278900393938002960874934247961607871473106777527720932051223407016420234223167654528943484751648903733229243045961065161489742443005110343785515581413137697763987482533173245412198624116588784627589113700230491291246586487931124398230201286498358983837195307636331765313885680173646444989410048686259059173371375205634462822497207525967661501853297821405894790267845254932924382054984572654780691867227675100642332072313312154230982361493179515196452515257362137928224721790854337178716442945641213476542060895582683281553297537851691166320768417682914057257408664922301780827711956163767190084649504182196661, + "H2i": 16049958866507585835384815005788316538235209706039409972931027027229126599954328414424159349841129632767398429586294831191865053221269899935979499537360938524423527203219499065050630632214647665009622593691292984617984319962062280580769983384664093202793293140049471218509331017772806500175243348065484855765254052222110265634711515565890546108071508931582248915040784157013136600141836331021838596339861326052338101198879257265809134726044554946078420323323621466697291893460417416647495606876739859688606939461520339236364122681516756742957882948632996890604196093637802132307350512490514330309497445841728301286663, + "Alpha": 4434289267370096012396436893647787722731641043304616834086640538428385255968951510417337570319555175328428083727172073245070982135888260385788551220706361734720387376942830160486552958160479450332120007754089793739536072576998600916715993512870507321275621885538201839890139768298781131869596923167041394891088069524526643520800471771786787861365518573636508585867906135609845635973204407036647425010921891483377641295983518633000849495315787571915381563653597906701624676326242006614928567193057529269190319897945013126073559172779465772259234741369048841621573740629348489025719106008532290826782354170319223011628, + "Beta": 3107991538265375799417868228604270957622162607876641884642855185351948081192617445072967999438461485329188935028482582031643217267577544895463843373008307601508528082892465829053666268997640901798524817389560112785368823768064459069602258978166586696443726889990258422866420413398327195692339661075749190849517239659478016925226405142067270167956375067976615972912258649546798343214978941315289010038559871463355349263575348736943413600257861674112676078727772379850800071526752461195181364990123423978517235961138949518685541832414489765513022801825475498674182392048327863176234872508293722029248792632316019929334, + "P": 72431700099420495489290356213790424565826156367436485759724233628452492647454645911479645836298487493640453444729896969297133519021713217646273897299473103984657912272167944404666527428901464713351154576631619597266636214236908751251030852709635247388672511556963691024555082865353925816919364086243643162469, + "Q": 72053582891207951235328030778916647825569046331117922843077866355328557259164752549562909879642408527466467379957656039013395673057558447367978410440211531304340054960299632830500067039710361369997812560379548483052626470287658682358214233076909929416803548618554896279293996839367966290776759610887390159899 + }, + { + "PaillierSK": { + "N": 27031878793943075729130612763238143159036556026966168238297210838055977134496375773671774053427328728163773047450300753405588197926530962193042353856133247107231446381777900745211505608168398887801093805191133332885134264932128956385912612060224271765525628185622026314614945535835927331721054010711939302016923298107666454724202564125733901227855977219836603772181499663238779623383670377553937250483575824202848407520495336621147584061267028536185613653404629493132100142370212370686909126012976561693514534323945147360055614501453387793858722164623966927880981812086571900895204648488966346879677463741631929413261, + "LambdaN": 13515939396971537864565306381619071579518278013483084119148605419027988567248187886835887026713664364081886523725150376702794098963265481096521176928066623553615723190888950372605752804084199443900546902595566666442567132466064478192956306030112135882762814092811013157307472767917963665860527005355969651008297131398353397351224765510032615664831501079329850643624501720540923782626099365034574394959517983496833606006474012172426670249820983590878735625790863431668052228676992876527331178429066754124949388842247494257044360867417564904377689749883322740922633579299555183956209212054000641630291727717938818562206, + "PhiN": 27031878793943075729130612763238143159036556026966168238297210838055977134496375773671774053427328728163773047450300753405588197926530962193042353856133247107231446381777900745211505608168398887801093805191133332885134264932128956385912612060224271765525628185622026314614945535835927331721054010711939302016594262796706794702449531020065231329663002158659701287249003441081847565252198730069148789919035966993667212012948024344853340499641967181757471251581726863336104457353985753054662356858133508249898777684494988514088721734835129808755379499766645481845267158599110367912418424108001283260583455435877637124412, + "P": 158671274493530377224816277192103855343202897337394546746947808963385749199085330655872119404315862621358502913422815336096106295338535189792317632025858204119799467506574889743771399315400167720319993697608401824830524008994030027058909638927954982201083401418560880357710318497614765998837369237960958315367, + "Q": 170364036466129644528216828476566042849772163839507938185548413193546308932386316828916341160223994587822692594124496940198137266286526164635824769797044425676196217509651727888475369839442885723295762941841757021136368757624227958044433025929366463834631252068900652625075905883350297620256639067793333973483 + }, + "NTildei": 29161472028770218739704231749307098674025680182744446812821516853332700577073933126594191044613078467833455979012724145635406004812880738504987946560541961090115401375497620071035187905034534042654673159269192237429807861262210450976652631684888498657351392392002460156917054741194582616513029006197934082634517240393734271279161896031315097432643445273640659782922487820903437611589929861844709785693640643504761186856171986762726983988999408341749901146535080901906214237786994017651554758810086331097884739533344931007861776691634046308889082929625337057628864542969610018462651464385185194654185084809622599692721, + "H1i": 14570670390536174039529319731824161100378939326791232344676722511517410009236493914871398153784114105487498949436521311119573277886098627972580809530198317510803339261292065814990810087709272162209844966008846381890791190662953471590527995314137777079245025384687569801674570496856438571936280041651347689248314889446782757014575350623005528824285983106358728988861114435045720597904001589180168545660180325590535125055882911870233147020951656314016498058008696778192704695800183841334365002788118175842899187916130668695086993739026454763363130289997616740912270314017664921065205451609228525891707375127849333287419, + "H2i": 792800914287458814598227944253986524940385261255528297578015957346253015454316498175183853552868154828321242509727757029330487017493056349040166740726531292279025545323739726334061668031008406538980928824443968957660162866385913688681703145406888983898799055700540808018064563812367592313431320025256736957369887559713311276797182803550331971266365838027278095909290235826684125214536733189008647594342362438959749414700100527842373183968257215608611533896375953956528161482312395886638696689061870112149171329312168837664019406322621879621213608845758084762291666761599208018829400075701761641062437832985123044811, + "Alpha": 26922096051181872125758904429596015477174321698463279424387269240663696575222178511635821726831831583365692233524889306936650539149420609429862748341392355568629564766255483150774833963679195604052127881522733702068986214006859227244116595570300880121192182550706131503527902709043168819586686237366427160303907591665063796473941144417108553904666461980292390725459020415464613378854680973171413905213736654520767252783434226687883986215938805086178666846732721710107435760461060421357106384028672994376635824639823369022482547890694900701748350488862424205654276615285673082814647572220803569899888042221396973369465, + "Beta": 811331280765891658575051431397759452914375589400483564900894787588230683064550258098055193253806734756428390366819746746069430438908156944642261847114776657113303721705403411241881258306585210664380848532151285992000485448357291076485959638139238666054582742861843509205200722188630506997654820530748097961750667168402638590705919951438794459075383204261557725793892920057751914460434058267951175543672461229259905106237165259709903214818016093484405079902398807403669043052960278569619386433676184949870740450451140323895247738680146870148010949394616629797462230346791071450966971122690726013248138314844696220606, + "P": 81253739302343717672487260874466691188076294739529614614992151320331800029473151087665101782296399880588047307244254457267636586985815491133851112475025874050334505090668052296364462258400147762164000585612067577144123399086048428282929964378738113748536775327025679249504111527775783008234277878888051938461, + "Q": 89723476972120939501297441215074188098574203211681540689623793893547759597752093036158940810472920534965966255351900240985497305720709771387348571076832164638740066258684307694117990428839773904247795904378396405031323870002466834557738004012508014744932656069034631255149726290587851548249637526873252397313 + }, + { + "PaillierSK": { + "N": 23176519199098314473440748640309558297646540572083426550697025492666593864490201106835029700609695384766859205021975913517745538221585575214976064341851145177291305307313291530299454994298621732552418241651073730398741796697485539118671338866697748534540173531090830591646578083857880787938615662796869394507810284107268824146740013478664246034593131316352641541283652975533674437589220834645453420587314472448983247948909487739773536197481170325322550210472496201442507734145264965693181466118761163263506598419858691361875701065182497503959811804748440434435933186538162968134610695809896753112299054087914463991821, + "LambdaN": 11588259599549157236720374320154779148823270286041713275348512746333296932245100553417514850304847692383429602510987956758872769110792787607488032170925572588645652653656645765149727497149310866276209120825536865199370898348742769559335669433348874267270086765545415295823289041928940393969307831398434697253752230004761884302600592951565341860685264172715654385564459604122080692543387172826721662157407807186453904149112525286239516320459445920745245504279138328029456592269923768642353574864553258088718254706200037004458570483211589926577616174915039640463113104691593839201992299539829965402532351862311768554366, + "PhiN": 23176519199098314473440748640309558297646540572083426550697025492666593864490201106835029700609695384766859205021975913517745538221585575214976064341851145177291305307313291530299454994298621732552418241651073730398741796697485539118671338866697748534540173531090830591646578083857880787938615662796869394507504460009523768605201185903130683721370528345431308771128919208244161385086774345653443324314815614372907808298225050572479032640918891841490491008558276656058913184539847537284707149729106516177436509412400074008917140966423179853155232349830079280926226209383187678403984599079659930805064703724623537108732, + "P": 167249952878902168947645601325799133579967484581733489610618546363587785665833270502118404215394665467447546498702515443469102554556509485808277042389735373220622119564747057217321473131984494024350169346397463387223084005147144554493768554419853372446969456907092816888858469377753660245617236068558739080347, + "Q": 138574144866153372591181974207763179642635486339599280544115220925925266836613218489891692057104192608627893151981921723825401002005768998023782159524484172162972430040670371191152843257670153061719919661061153965735476093612173096310810900498507781062737520247882472841767627352483162061617114294732187802743 + }, + "NTildei": 27590753261596015481865073917256518970445332116891062415135288673378594822359668885192228834615984492671675028015727373439959117019691410515637860359925476501012840960085302072027873333201869960351524315487308508518430963997416614298635396828586569246534589834736926011057208550995063525340170616139958834057137689101502196224640728623116042872725480109207873787704691958286856055640747472754741992265050028062641275767673512969752426566948239819617177028149281205470282374088232283159109786669264376174565202528521722255536650689343351074814798475168380738799857043448512563931263341885549831328849904146335400683169, + "H1i": 3570543848539734312515513973206483292550745653153644316483496061554675361973711224550559460783091481415229209286889530549715550400898897717301595183654039077585523189076523210867814836355937376541278539558865846083320865378602307651504601261941125945190144014444620667042531150044197954936840429467271107906513206869058453562638569806132987404508743244766565779446798392871379224006092614273927528887395581052381902942686322730032550745365928790839226647538498584487364212034958371158846078913873199421909552470568656133689481195301546513297202544816320733007036366529762885113541078606184805803236248020674404888866, + "H2i": 10215181024519776296744143429258863093156099178145110406603351943792428344436618740099828918958908409742829600233915330710324920616549607477579337485319061485785441790583535182766335567049616841002248347114110914060966383232348101894819790306236457987098459047404661444024051243281502214726447303006280331576426125798121127803196663786582409175034902520720527169429064719643553355255838626098385495049738542708761914021855422875602997131971182624195016085397879172157524940432007380158841243459642055476131551563529947903150866767210311455631303111458684222872839489387310994010362074729062272345425959206227527070686, + "Alpha": 11958790108683247358980195872716462235549860779348445269952336827984767300783138872276230860344635309184288975222640879424138514896724032346761361250488954048462902519389637871247005637390837844010213496422054123876604107634340634832424238601617905115953365534300411102006565533171075225063496372069848551593965283007004503633070049633270566280455230034313081159265501171475579741976553428533709608413746653631141882909515320650059423180786051892756289648989667469445820579316615988959131734619211154740309496240434757778549163328132354192310740090452922336684669312060092793409130031641073256340173545167347827577009, + "Beta": 5846812149031014697431228142795667876683805387192994064127051983268914854218563312227656136696349539440175961131760914983732526239513014475279460294254220833980705167890974833270969714945569113674619240181898586779158224227067593014047167691233847313916090733553202906184038698000452871724556419631905979897910540625295131063746315365142190086016062418775947406604885604810530461187251911371947796810339208677961481857971462468906409004139213776425806301911056039192659015226125480405642641101635783026476584021328855528893946159700727807910729564270896915370733783458019363834244453152724317531692853846421592010705, + "P": 82064494997940979838036971177384815418179367288650897634197049943140640584035921045552117848048729748430332449780832982336153925774710148655899894468719889349487229132915704429515165441880502736844615638585262096402154314546356071543234582100741747115046954616498352966597718044177703615950825160277592340021, + "Q": 84052041209442265110760231510923501290035117659129619963999691739162538247018334926444820192434576816224385956079766914251649842337019665497699794251440354748128644305272549984765727417535005933464937151875859036166023989069042627609525495054547601398134176714992652491306666382651140496627491753973239258641 + }, + { + "PaillierSK": { + "N": 21266917380121412832720277891977216295202824379624987819968149672847639361511402334307194012758550159406504625632976294503459864182899320201059962480092629504616996190017330881057659085300078140109095828515177856785122951784061658504060206202594633881870095577438377566795373190924549719996791966479779093218399183853884101646910678959808473684287289456269987188067371037025297033666729506142693960195611693405909758957852854745582063996055952305847811952617365817077957595177574573882324892213215327473929147316587172597654215768692434258157495330472379723458918500546028917665516409819784298753368383427358333598337, + "LambdaN": 10633458690060706416360138945988608147601412189812493909984074836423819680755701167153597006379275079703252312816488147251729932091449660100529981240046314752308498095008665440528829542650039070054547914257588928392561475892030829252030103101297316940935047788719188783397686595462274859998395983239889546609053347734213171560623900050022029197569553140835954969200493190038101385979863514282039441526054431258071646221599527014345209926201034046361578385624125728622497655920774193852688112864291011178989274456720037575069791640985439031920810946872250822273537461974405612000720084103952156994872965403882443215778, + "PhiN": 21266917380121412832720277891977216295202824379624987819968149672847639361511402334307194012758550159406504625632976294503459864182899320201059962480092629504616996190017330881057659085300078140109095828515177856785122951784061658504060206202594633881870095577438377566795373190924549719996791966479779093218106695468426343121247800100044058395139106281671909938400986380076202771959727028564078883052108862516143292443199054028690419852402068092723156771248251457244995311841548387705376225728582022357978548913440075150139583281970878063841621893744501644547074923948811224001440168207904313989745930807764886431556, + "P": 135269379436610031009339988917998764551549015167000221670402477566033813177188975574846909468182533031549633387324597993237833725973899718968280286658340582708852798634007417505622575704987996056701242499630268151222748577249251933634199608534028296427721359681318171359151968073634354602062744595800546210503, + "Q": 157219006021148494653538870846416524596634159431077027995982179383060448529813502003768167675320297858216833127329202723653810417679984494156374894710773777124109484702018768671326090779645309059249355903516829296291883909472304260681673828193849782484122216915899522304924273538245630161559708023792900956279 + }, + "NTildei": 23233458509227284185243128814732768015181979242278079472383075879758044897151295119719831622009733299550452846543257724971457163667600607351085172870433645910938272722342808784490602144385821169420372857236214922901467484119080853262761257873155943185686322115211549086080023030520623407102079435384925480774356634350795788370033442456312870894322517965220379878947489336788369845819480370388558790624199561838182116604246026065772728515356203582547220245903534914225699658040189511201539868926387335747643362673269036758751057988106728308583979276374390952658318529836256172994194104498466931431957151513615836733877, + "H1i": 8895894383591380071728846514063015196485037059539880432458177344031562152443461349397914276397793139938023303055107582005790716873478881925342401515466545610829638018864329163368515948200252781444194370193666318401281489826353333983588791442051726546588558208160099332266215448972954829885174562551282521197033637172323034641635917613466904523550513049670799575592244715720325453070169610757475869514002460648103952716023687897852710905365403140015339484222071980095865034712793179585070531464617221568006585961276928369882249129976023970091266423266291050242475498162487897313898597955941006359536247452249334533826, + "H2i": 14177442932827383415103121267661501035183327554916763510692838132230868838349745684668957428714865568597687463024801762611058395433520565265361882677409559044857714640647125674716502623635836097469722616644149016922267325557168532852852469889368336416108242847581123069659648504540802410743741084863900064894463538990632537516699805949839449031259891510590312957638963894635771565782430614612890151583871039525129008665865019748056252641678443445061017406927760625768107885748482001712125823317770749732718994037857218169212241747436362404282699047985558962047461544266908552048448520329100868945750783273754830603239, + "Alpha": 19617185446618458843773140700401185947254296214438215880218353697391045835169061040703736432403727384782522478895664728308084571570419652892297292423649199649471673194080829197563628625221465439675802104076632925423940062020057456538266342605414392259743205505299435432456149950701006822343118272178562540064853907685787739683425046631837325525158912879740921025772206733075168805878231875794877351798039299863052090309857348087831227321822403814092524817329771274737240754327469208789173719308329315866922188819413819494006820629147221264874487321458167776753364993354313361211073634163685797968913254401286081749310, + "Beta": 4122395702598083179295091932218303594228805878931729422019774812289837244384207328144035108722414148564486459128020554929566984145284901496486996747544736659567428989995335867129886524933775344903623088672905729069092541611658476946581539363425576744570300845319131806360197695138471495200293089710212530654683250394746277488696815751083539655257044771597038074383920384203775525151629855521250769210627560674019573640219621697396780431370376013427892168582376785028369974369762213615586019032492382866306054585420663195977147313047881371798949519054648653947258633311852776461730438848351157850989875063943139424764, + "P": 70321095922550154646142038711735281562428007133616394651605572025598807970695270674171360429342160568455147345712313568129274635752794557529994346545398505685329402447661270506539926145942679486117585462513847745898583194205989159874612511305762929936984466401786062806375240436855393407752669559863656363891, + "Q": 82597754643983426681279282791972008328751232419481652023033962007623106852437584905674527871079010317472853490210863417563326516328551428139282143301311609113044739945175063834551869335414222256317430245144962159273281419366424296150088309041563714056238968259483324029490701030983239770438480687692382491009 + }, + { + "PaillierSK": { + "N": 23237136416651021905534362410455016763738186407045432595528243606422292547894044586919798268403688594232299884353541364776823476068743620026851307207952654848926428925387176781509788068214000251805152657341923306552534057070219668728062141175234242925873260687770325910940513138249487546975315130805974597038990925173267114632972128307579109760164601372665452044109555246406756416134029904451334455535019680701779741833639099292724779144831368388023927580404894720920251497007373016524411327527971509916951811003387606608371701565077533607282499628980632021670783054574572198498958491560945271621660408644209032644917, + "LambdaN": 11618568208325510952767181205227508381869093203522716297764121803211146273947022293459899134201844297116149942176770682388411738034371810013425653603976327424463214462693588390754894034107000125902576328670961653276267028535109834364031070587617121462936630343885162955470256569124743773487657565402987298519342889030556511940099645203990336652689282897142863775561181186596235070980032410322607879722003916841194333107133293786338982017220679782120919415413135318248907830648023424845477533773828191666362126404598348803467753866294472734701890753806946722646936621415276615648309999000633134439445739140781134255238, + "PhiN": 23237136416651021905534362410455016763738186407045432595528243606422292547894044586919798268403688594232299884353541364776823476068743620026851307207952654848926428925387176781509788068214000251805152657341923306552534057070219668728062141175234242925873260687770325910940513138249487546975315130805974597038685778061113023880199290407980673305378565794285727551122362373192470141960064820645215759444007833682388666214266587572677964034441359564241838830826270636497815661296046849690955067547656383332724252809196697606935507732588945469403781507613893445293873242830553231296619998001266268878891478281562268510476, + "P": 146127348095271270017358025397766836661316420641327711046696021131699969944846619852568769096783819575249791192959796393669798999930465973386960967337807903472187653077812726357018132498562937825113680094090943439533898436106853856189043526479633641019428818294359436992886250481638501451852716218324498978103, + "Q": 159019764058819482755479874200669618124719157738396781940496852082586304229118463953549926994228027444141284426412715326377016110459542850395127782240816180950248182633513440476438127481752188759113878100099965561902295396381734281689674594887104935357480993449659530209452243078040501290916214144322265156339 + }, + "NTildei": 22712704688619635803220119456991231357411305286797581330897607730285647842774215580942176867209302657798978358761090312064259018366850027662393433967906123931646435446126273565419718140244850185024562422349382682999135567439325659338991658547149202226275407220597399004633897655597244648010317241145601568753121671030525774431355039855332984731422756081010692547130001864257997187767889295880006661178749668623015929014294433988485089277025104676728135301592688595905005621656436667083294398340088239303073150780934499081257458412286303097423649752617165218547865942931741165907896543562900959470036747094236046611857, + "H1i": 22330289651865458499079405278275139668273138438217226657909854098980391561817274763914542876603707812869932530024126179999190712295580367033829939475511315939957921278612623929564537391848120621258633410084592607144846951051421036356100682187923928442919434979295918435830309803268435395551232195216718505097635723812762825535107529931929952911183232633363325538743522030720678786127649678042197290535398718343569781676652797259381155960255346550972217847712833447349906375022608176333200872208862115966228769623026233970178166919687707148107107984571137398670623354299940604858660914064746374948143385468947060361927, + "H2i": 11166645518007042290707642205350642279293558621833553364395179926087016347300867937388340768157733526667519129710732650397769189346987515618944817768088444793901799929491598297917182866318876608138221106415122615472353702239298942145587020155417009189990261338639907791680053503360481537631589760341700182325937418530279047685954463133418865683312858489602252138445355490334701297115923527980293080360579857091553090218213168428145989651857248730872402651164944687476515013767096624419173195672843867953811368829776897270865700890166577534327260493157807435481270859057259152297602528073279252857365951718103038785336, + "Alpha": 21961858383430729091595127692376475246546916975869202990808183977215065492011534294886426450553637530057898183422563486094916517861513004816886755532346075730958705717607117771680709611046777089973684143274645933433855092237938614435122086902564252366175120933300573431093221274482975043395770801252207519102585127156669202067950816095365876109743000449215383843100413510237441480313149172786152327789754332184875892445584843869351183636976880680565084677780863976167501786693463080029325737656423537741781842000140273921605469738871758876652219295202507648638793978352752241009136321456338651173670376780991657444817, + "Beta": 2757595113359670333790710336612667617879818460452997587240341098135731490553893058016602610967837191703063189630525803908840728915203890632812643827013964879029727815984801545920942611974566803489141992436196041449384711718225860379178251340526177581675733086563388745083502861701635309950212117769476413577980714700707530752932731097090053729225801367166061182869949264229043282302284992700060198743000157010108292880241279301613134198649103235298515338130387058399545079158125371414055798339852886338281667711765804934382012474001563614669080191486510832623608322723180161662317546051827900960336058552641940908373, + "P": 67428246151895955479284887615059966758025997158513242025696541556841999947828174899962652920069213614561257664920354508167828790675793030179010666667895583102534862129325351996875268621987188778919709531638955510073033845747571838129933516469548675581796190245101513298351453759472485945310516453223913592731, + "Q": 84210646074994334032000088461783564036952801268655547090802737462410951128338769908753020419351477222387670374980338303600984101560523194774539349909238793549844324960901255710238692906624434972844634821598180403975996223459824594557364427513654761835902198906180609556171557344102920227404278545001812613819 + }, + { + "PaillierSK": { + "N": 24496882373782215488032450173562278698970026594214580221734744599892233151825253846546334202049482263310843653710368698034313961511135267274276704888914033687674623502373800229089726033158303234515125091898153949212723433565796415534558786472652621533597057820004934433654138974631630100729372137373561862500348422181759354732482264892565909034569927029961910160461701130255234601962762730220157181748735503733948425455961103969981742249576057628393644411021579832453791076603742644532727436643777267793325577935832829189826308216829189017175147721629935225586029187553375364800340857393131666682573879031283908535589, + "LambdaN": 12248441186891107744016225086781139349485013297107290110867372299946116575912626923273167101024741131655421826855184349017156980755567633637138352444457016843837311751186900114544863016579151617257562545949076974606361716782898207767279393236326310766798528910002467216827069487315815050364686068686780931250017161111163818877156124251490342178017537404893202613866378749461704204777721402993055155447901399767689819096966091519236306691325049700917024537566861845538973134240678335550232676593824301479170190097791253940277181652090695258726068730333870606020185446293406638655658356711302432764469423745647618795862, + "PhiN": 24496882373782215488032450173562278698970026594214580221734744599892233151825253846546334202049482263310843653710368698034313961511135267274276704888914033687674623502373800229089726033158303234515125091898153949212723433565796415534558786472652621533597057820004934433654138974631630100729372137373561862500034322222327637754312248502980684356035074809786405227732757498923408409555442805986110310895802799535379638193932183038472613382650099401834049075133723691077946268481356671100465353187648602958340380195582507880554363304181390517452137460667741212040370892586813277311316713422604865528938847491295237591724, + "P": 144095684869385857560297441927379842722987643966671405004091125502981217444402634001379441555595062990945994097571463892360389271998665223922482028405740276614492796613139211557560743781241410304494760621555608283874693682504772578779168928280059363088809982020519652431206427338373914266647062187627021358963, + "Q": 170004274562331120609718947657844835811864576208833527724852505828844974962917290232667429297337641207622793164457457039148739594927293002637113307482115864761352011509246761874701339674887254530490437118694713025397251230143025920943841332682134650456848312946042435057817716632152886886987969352361649584903 + }, + "NTildei": 29862037543484952558681533632486107029577346634993747671661621732315773043394898249575367167534744049795361736816183673843493221627756737888675359048632486007412071873874191405581782623055684662073779709944130391228463180465843133868209946736860281706147469871512574816081813404352891487728540293472347116246324635016287092435201050674756458241428310268862644870205513923066772876901605199733269149722119724131595139817540907195040644328487324065283993774397618688125322867084551235848871862295685194314575526060607347196103388717633133049034857708246997247540521042317763884975617737075333143809140064859546349264121, + "H1i": 7794087553416503410157576487891796343776108099656854948603888163021923408342026737929950811852456396463295664455646222957147362021696990426625851057909390669871325482386435038609527130770799531131018679059021584005665323921530734020519863392308023065415645578704067218273369770321333945438342328012754228190305359488093501507859211919848808133414302590732461528010683698650031992752536770118423886553668342827114136841187167777163848805920152155906933591477147239889316945781287105140181545092814740967688119815442386255717885477842254255806094559961702022061009738205620242147070096906476451257758213430644221915766, + "H2i": 21089939939836125854987704962720414572113596622369721605059131418137463330360141851437281786385452377290423641700803611395479869735165566144261360500961863729181778491546398348007354732714063399507272015199249338921387801144628569123632626588614830503597631958036150565200901782101482820540633202999153874612431358599877359585773016585875852796338190907505615152429661521817732357291846312534032370596477358290834152131036825480901665364126106203658486749382186407901605815260638904026146698182766227858757805020828769158501200753662675682041427021167734059932648036684960799493850102989781533107645465884770372429355, + "Alpha": 27081347072386932741856330082853614577550533343760366443449264882357135675497804274546357191676177634384333821824071101400903958794075810990664453840751133029697733602561827699346981395444357954276054276517836982476136035275164467707193884334123277398218045435630065712604817138388431417370969123430340551076977359203595652111981643842485118571262001967284906887187527120103837784994127387872259609854145100778909139770870414995874906504334297415266367235783382786524539762098969446330255722823859374767405622384820899003149037624051616053952038301005149922975855712405681708888817726414956238849794572742428884301248, + "Beta": 4345931347790553618267207449265994092796603174257087343132056425074019376624514887258300326674208038768851511801248694444385843202480385806690332906111850696401460091521535549847893909886793176067142066814437556645071079922773354789940750000683391043307546645066856972595566199480407059908643225958882948272520827450465543712994205521958285971047001157086803121519435431562128593575639583142785817962290035163118764268731654613043095028268447464142489670656862672164057310044900816318195781292408104948562590881769417453536901357676005506861135052577119451551830132536523660786277088841355856276917425823021322826604, + "P": 84873638770231469695007521203876231804248075945680041052510635761887278978219018356508549963829074634811124205961682917286799874639041448982265063532571257830925860784426224850454393230512987612060145458069471189432645371940771105499110909180330740758460202289637169331576406328102216584110664504278941774613, + "Q": 87960284182957482965918315700735999427948310409362080121034470552002966127621188581713482431944286761246864981836281479162864092234657632047216874139030940846380200290182617896507710347948292114957536868662153407688712194790220021010685669576565927315275090061401556577342145179573158019622177800293130599861 + }, + { + "PaillierSK": { + "N": 23906516189589131148425956083394143844553479971531415573907229725977752213733291828081420613338985242222654385259202035542743953550898506435102410822474022599854787463078102462893910472834890419391118731341961671380692374833813708901445085741800095775208717762814605976541861157300452416823766666040850940211016833608734913194604073932372836378740358464889765433136491987434679369947069762783177740219725596641801770332363594018828521148097530944018201912976893899261897470436134815905355728379464673100704975776680885556748864120893893105265366058628577191492814140105593287775138491493273091651057994769919202730637, + "LambdaN": 11953258094794565574212978041697071922276739985765707786953614862988876106866645914040710306669492621111327192629601017771371976775449253217551205411237011299927393731539051231446955236417445209695559365670980835690346187416906854450722542870900047887604358881407302988270930578650226208411883333020425470105353197725588610611236121466172074276389845108187349199505114869087991675394991520283014501220892005635666801037250445886543724505994907094380583802730761544999911897505766836038345603522010469847325165282563407814398168788657880876464153442437288496031579662513072530794061402950000323827048682248762008459918, + "PhiN": 23906516189589131148425956083394143844553479971531415573907229725977752213733291828081420613338985242222654385259202035542743953550898506435102410822474022599854787463078102462893910472834890419391118731341961671380692374833813708901445085741800095775208717762814605976541861157300452416823766666040850940210706395451177221222472242932344148552779690216374698399010229738175983350789983040566029002441784011271333602074500891773087449011989814188761167605461523089999823795011533672076691207044020939694650330565126815628796337577315761752928306884874576992063159325026145061588122805900000647654097364497524016919836, + "P": 141564547393094764303864093307308992732791566732082224151369749677408500252568116652740812801534528638688013795486477438637207250328195572741433347506557594478198675670433858049633065407532373383424655827847063898866290502895790663698276366745743210751052685278451981437840293730811021661434150601751862950259, + "Q": 168873610164597207827966906721378833227876681782984809974892499581287518904518605564407924976407056731780154462376224807103864885779521182515600960008813214783874999754167285779031455927911360022629989383707006029086236040682340688638782807008256988678602129800996244749175391862461422335526479670643322860543 + }, + "NTildei": 24752031355317329501124445245299499109867632270652125649567231081088665144534959646938874511638963593645398981264846892895434875195144188518476198244564737466064860745291608215199668426310610588179116374469142190782412595522918640337947230461338616584436571727471389003275297026199129655339708049617441868866161100996611571633736202220350269050983156859896816752971686345225439882870473168960299320088740963662205201753350127651015145376295891396019691826634983776714797623856080342997031956395519445793177105802930474063801528553485738045092527492821863231067227540502731646429636115933411142613417587831135542331501, + "H1i": 13957028928210741256105162811408092895219318725722734127648519682310225251061654327708116510130967931945457375118700349831992404911494010478819262999458048714513649117181942928804888134369183790393204345014378808916224755634490033398118782172722845740046127043378237642731580203882669977005038819530511480532496805935335381218544002954849755132813447473995813853747089833320323214039659891433372967743680331240827013294260654669404846537422250137381175011807846193981896190539692198202065632986214585729761518052991105733362852229708661019243387433055217253292396797720150617090576695621503168029990050027816047937112, + "H2i": 15752902183140403913249767176962669116241285684822865920368751336603165771448407341233452106576792336182302163734730172773492520842298554669264095294150642555907291198925204414417837392693535062967109655923196281577185976216524781194896194073023053842955495073295016904546059757447405238434102270601125217980140059320946078564584649670589856050545134574039453928724885732468114975835355280265032178042831726992499586531551475109069369555621124646652558123416155068370688242130991679413852403408970455256557524480730148919478956349927485139509804183566916549271390008320247367640997782040491920972529565174114929839481, + "Alpha": 8392891359308598352321038851876787554985365031665078500400971605208556500896532830230637562043821611141580458863266988696170008582719044918743153605746682255391552085191977137899014175096929156679413404210698313955983421438113391803268846508706208902016342058787240555138617430957726435018993641384272704739631990325487777381138944443738210694549848608829677243475072399679645927606005514286685510561264998787698458312516558296990601381416044688203430257022541216048001547111523895914957704658178066363431936128340367489485908353053190120423616965269833876600821864564125467997133029509795414158191930903706463721433, + "Beta": 2511384663159947171848577381456670030202069453112933690083763042503431725605911432818446128387213227909858685783808731861219158545948489157692010396483663460987480818975354599811633433858285157508799966744917089363596717682709416910020865152620832152886884430036855417184837492238782616280420716961956880645302042186585327514925602898838052031767471084682075885912773149691859240930398375056022925095549476440906269753897796392689996791670274860669925830819246295248510808095007483150757469522228312659182217945939448352526491281922919531767950737549445480923726434619431664450865813241399423202539189402601869878896, + "P": 84334730228853613493361154666043505556794946846607634722479260020138533156307306615043600707020900906641806097691888332882802687632517276018526948979447828548040557447380227811686589377196577107144563561888105663807570453806518808386387148985107566148578090365670664343712641831758266037345089816045766541191, + "Q": 73374371650177124955913648564295826914400543620938722781627109839160819998327635684199058950499412660302416092595828220093461853341269473386176481322610518000535738281366033308321479090725113148898075670859078705371538865064055168034045529984226177786748536728142461046588867058018727060870195984489381298273 + }, + { + "PaillierSK": { + "N": 24557717486235155387918555720309017052841277656823620909281437342057785785961160107269860481929131609243559303793968249300591857747317588295556342888898289642397105347765475078003697628323575952585323816216110067678339073098688287402086593245505608412307633186103670728036882513733369973768701236408917017881089409834864186883207691306158182222244930731834399937032206208208284279907588127904105406274802200505202815030026318360175262568441080017563800516935278078525151354115070130974112322137750543601605933088753053546219918084146299667524346839485148789457043281859983443135867651151383077706617584582443104054669, + "LambdaN": 12278858743117577693959277860154508526420638828411810454640718671028892892980580053634930240964565804621779651896984124650295928873658794147778171444449144821198552673882737539001848814161787976292661908108055033839169536549344143701043296622752804206153816593051835364018441256866684986884350618204458508940387559432963968431906293146711339490095333485564893735134945159238370949007228149836087691956958097521850840323973792800733759107567348816286236257985388212264788559100213927081605038580357049366316656813013441105039866074602126452858048379011029580737443067085389871409799155651107123459764048839395772147822, + "PhiN": 24557717486235155387918555720309017052841277656823620909281437342057785785961160107269860481929131609243559303793968249300591857747317588295556342888898289642397105347765475078003697628323575952585323816216110067678339073098688287402086593245505608412307633186103670728036882513733369973768701236408917017880775118865927936863812586293422678980190666971129787470269890318476741898014456299672175383913916195043701680647947585601467518215134697632572472515970776424529577118200427854163210077160714098732633313626026882210079732149204252905716096758022059161474886134170779742819598311302214246919528097678791544295644, + "P": 145441391060835264640387589255377428421205304994677028339684201644568732713036797069009889135329297017406559270378027750063787514419997145185319851778255116117431088852597642801636994634233821847853212703631394058960630111084342670398082741603619666756111840461146917428764470956361066094073913696544749621263, + "Q": 168849577875414754754717423480125813633058455709935438422631688086973649180095031162920133225556708444094575111700705008643956838886385239806008149186246537878143147062044634009265250342802623021119406759094777277179555823857704091410167339859469961226045307228056782887504868892807764693015573207106810137763 + }, + "NTildei": 19507046384150138572144834305268791872010813184844953408040850818518487551029594815520703930963345089526077240055304331134646011597187207322955075968845313870636807942623732000855179797825038395790910387546565984042199537774282663766074343997758446818093358577822893234454674422879336199643391795086490043865495070434116466060891039051414041253627623059893345095206211866816515255699202302718931902853467750752258454430632410586281595858823376331926594035622699106347975093181136328098490123269780879562526866904729317363462527556185067810958285187041389905719454118043345773949543771312742159211704694221728925050077, + "H1i": 8245833386230568310765713172257064449197259971857631689665327499611661778853739187560098450905136971808814010143193665846552224416876610335337495034996612242487546666073384898179629788970135118510318976592035918673931386035695182848707063722342178923819608100396252290108861177763594092536274835588284135371247026890515532140512416029724044103863436908249647477024338010407856594658517925180352098718209395852983800645012833634869298429110970034461507519938227765745609702820069628169428287747743008572216661930008062228046717142999560769620084648452008517128582066210040735923560162004324837284472283766086240096836, + "H2i": 6662518317359577123145717470150229332038308455150233152068417254358639567807229736126779922940079881166391224629537914180524071112284497690569981245757156236540684716758540464458691784520370056565556686406397362880645819346553206344733894429742236742916811462727333102681152513750071546047704597159501130452204736829145527548467053749585927820998481425676393437755248443448026727332021245980649779108892056267955275135835566967911615594500190375796478132494438004442502039336011987747012060209235136591931410708309914746175121094204290982506974740468487274805654853499909957969782387771409766696884453102351335131416, + "Alpha": 3533506718431649608188671693898277036043699465683693225480087098696912731493906328618955801095354985634451732465928421609329768105490857925455786200487495141329002288426666974212290776721020695970795635312255926948598959366289415555230667583163470639559899883880780599150172809900311914055478803741185834694585459738270292583948208508711543066527251438356356100937799450078265864644112516387019986773525417627971132799731720214110771757309478197922289037692633751354828866653701626682554547048084518003394985447198061101471927202867208296328090805306638501751851223683442847650465419060133203051430135203198450120768, + "Beta": 3837104910747413294698833671032775503465853241585556273308122197618318367284469349800057061785253387332430646059570331296283855348596021217218719947932314002898335688348247538341338261122007272048383987246067779833378264067441345343871385754147827273715309409861401351587879087995162613109810429088370486193844939398752732068584416788882953241863614176295252687383768896832163016014988645130482912536207488841807056924773285228518945933665128242631237761209365227461619406419258165443582296267668734954774393700391777339406794979021304064959686575214702852860203596397524802156271781677805262186555609843510555266954, + "P": 69351714499164352841133544376913406683568937707575625313819384890308903691019372982979258583722381885057274504707274006060020607382560101137652993277324409700126361862211800483805840387836470256355872553997550888278338523689734909828660125401263419271788066667096560789729014202857991374647135948147098408309, + "Q": 70319265086031820267672376218854030151853564517560046378002777739638903944036400782192162385417057449570575912423159687263756087880810907761489988125136593947829990759802275190042270643210369254073545966815530720194025155945643476151199919757075325138557473043313997205666013125376229608881026542929902507691 + }, + { + "PaillierSK": { + "N": 25426930280784666607606746972226629816390836406101760757894333828851029177396313132730655355064438268913444990224300279043966882115390306871005750107089676177274291829703478768049119475469904646186102630523735407099380813635740298491615138566299239278552219991044636370637787272057476688597457158870793249725037539036971801038135589005018366548535530853431434127821016870504508369974942516063592405316224221191332656007197326930945916544615422255745808992711196161472306662077695091105686782643550031780976452076394298687738804239860402082572012384756023741770579037265753540291200330489663425305591300581375810889737, + "LambdaN": 12713465140392333303803373486113314908195418203050880378947166914425514588698156566365327677532219134456722495112150139521983441057695153435502875053544838088637145914851739384024559737734952323093051315261867703549690406817870149245807569283149619639276109995522318185318893636028738344298728579435396624862358699664207418825910673720038067370128907136897186808700304312815355391143066534039055753422546920363539701047072081735274771209590744927853739632558406369687028880092709197250898665019270956959199921471257375060482532259385013951988098571993393349328980290825656961781826803719569685128445102588733264699018, + "PhiN": 25426930280784666607606746972226629816390836406101760757894333828851029177396313132730655355064438268913444990224300279043966882115390306871005750107089676177274291829703478768049119475469904646186102630523735407099380813635740298491615138566299239278552219991044636370637787272057476688597457158870793249724717399328414837651821347440076134740257814273794373617400608625630710782286133068078111506845093840727079402094144163470549542419181489855707479265116812739374057760185418394501797330038541913918399842942514750120965064518770027903976197143986786698657960581651313923563653607439139370256890205177466529398036, + "P": 174049409634418354728989301230756060276531813012877023660492793492856713949605599917193523146583669237192250415004663431948255146006684921688828313322967746108117285321157243162134592062382929353931479716404613268966050552365890035696827184392548381973972386281929880693043955442634264431528914478625353996759, + "Q": 146090298922545031585252263711475748001184766624183486759915451380940873739203848068287375324546711227061003498048500028448118979427247478349501414271415675990131616571119453441754860542625188508645129417474935297807689168724484142898988056376688661138646069332509736034502767607889790617172180925283927494943 + }, + "NTildei": 23152014987538474443981864957450108360368730222338387023197073703199433440976433721119932903702585830061889122997459572972844690769606360092797288933678706919780295524924157162098155600311393002473400910209963957356658059465625550013802028155727169700363447484560076118528119099603805871704907367936874708603097207723538730323658954300059639796399993396158312562344774347736583887241300539305022841528960825498173969262972643305310436646936922371473924843680433725492298106025160233518946682683995639530240682830216962414106728206472571391642863298532238187029385717385465486442670483492426780279028663755615213532793, + "H1i": 12363181421750072444452153498420993042576313350037116231651938624846418457551775473694639822398397811221519652689258641333280674215588840846801469149632637218166688298253175575815182529531923482194324995689573345176005159257060030140319762327721966645143072608315996530671724937422540158356040074069638899922076359012825782101241180054364029727481655087257189608857542628641382809743032244718810940236638105511593847511051666370951737566608803717062531712005761529393714976399608669227200920047496214547780535437049226346205234693138311076346155734041039255674281299179038758208010543919499255385180886777129494825482, + "H2i": 8682777201880324750518880727430336151575367311435059130868401069786606191837069210930238395786890242441042756933902325200722137532506842865439955002484930147247464305393128404164694537204425053815133102240036413219596432444621979926808478187380367130893128011362404450857820191934309874033538310038990970985102726202044297848439902949335090195087602893698372352019958041157912394342835348595189579600221136303879849640754489018914367774213098699094740589628299123379137333140334430563949867848205621548420939610736803355195666596447593023070453540496018637875123215912974590387664296404372760401480720031102436368406, + "Alpha": 4617978587674074448758226349434055245923046066767171865178528139557546473817889209471656442462551094919753982741044290469871444517380567587566923916405220517342137142164526582679036163875224519276649333686147089871775715705191811559064961881213137860577498599883550218659277625000047467838042413499188446039865824980436318014326568176132808728689865409832241745053517606831702160554334678019872824220922058016767823697286134042944313638667138452740824325553768735101023056491622045095767553760502024523604303088647684153128453518708612323801962178931147631761636141469209480555039362810248940530132880027138623051601, + "Beta": 1974600449454523560217349379232633340390044204213583766883468292980171263796073285185353966474199781451579426492710038603802852044866764357997300283120584177453623259502403305007963185868629294081285601130973097409195341794190324638049193079999781068762780309178041846968544346962414953396060315472083470477141587366684821990241669186133991772367981222882553414922668768724971497835510633327414762939215782335421855154146779461456630980815093580458602066325439917791778683099351068704002866949315866694238303563138827368674085431734323457239410303091072753553791722553137994922740824542340707450682924903472035944646, + "P": 84998605105480468900854274823253497096378152499620489718142831733832177400127384640158469225018989532246065016249097776827855436286983661496989681649995064485435360849949014203289316691525792449032259221827750396224407760863859683749326627775354621925849690457197225216892381907999646112515287951560020144173, + "Q": 68095279207251655839292529783557689683149923676255038910226897167733968998378999348102723331239392081457152347506770329592496506282877390437906499017149594678944043319420271013595706508888982644910132395728185124837296357162395690549467477569680425599451962259216349232483137777191017225523587314199259209309 + }, + { + "PaillierSK": { + "N": 21826998854458124219307940802461092566951186290501986871650637565426678870342195100975110929977196354239818176281702600243341119173726793397927776155413865970472030310496264853269101822390048334307025847078881477311574718327503293039593648518380865917661882932682736746056891427414821177732728302843830931095566318005380698573999655463978829154404173935275682305924709094236831344765140105126286927757346487413956467233229980431744660378916598801008582620632473192668588207632316596877500360405616745563224274371794331892662293014614785786411678774163017661699026323204388760203762843584620611929012968530214981107601, + "LambdaN": 10913499427229062109653970401230546283475593145250993435825318782713339435171097550487555464988598177119909088140851300121670559586863396698963888077706932985236015155248132426634550911195024167153512923539440738655787359163751646519796824259190432958830941466341368373028445713707410588866364151421915465547635139023705847036917535076759396950046845551245429382693188240375667461194305779969898533995364980061623377369346414385408792277424828483170135593420338756615073482523746492659099218989110831660459444349169140684158086445290447077594046984067221881095613922260679420151735662801179797538187630782996979907826, + "PhiN": 21826998854458124219307940802461092566951186290501986871650637565426678870342195100975110929977196354239818176281702600243341119173726793397927776155413865970472030310496264853269101822390048334307025847078881477311574718327503293039593648518380865917661882932682736746056891427414821177732728302843830931095270278047411694073835070153518793900093691102490858765386376480751334922388611559939797067990729960123246754738692828770817584554849656966340271186840677513230146965047492985318198437978221663320918888698338281368316172890580894155188093968134443762191227844521358840303471325602359595076375261565993959815652, + "P": 138914193784182425593156267499844024139491827112630413838932235546243011154590202065651746820024119185955856631785685368711258427529102733054772290695075776121614643359798262010876294783350552235473171381399161517111171804433552402843120928671520647522051767642835202695433256439261624451512467794099828124007, + "Q": 157125764184822074571429042960191230170991005672193126699400377939253411221938343120838112946592408104753855862751466292215817396537839101613539143096719903316826599225025349548425627644044530006832214292056889007234948319600339228380463877357053251985746711040194717204858261542999392401125239170121193167943 + }, + "NTildei": 24624801721616956273567956113327958160928807465723596432119479470729171575111646409463568823398051088156549831883967282061671258322996299587199085144384091339897578879264641087373178695707206825602430401156798050364091315150315071672757734095648723441991192452086888477851598942159299209451520558025003619778895631289413553080382407758681872227964422182664481944612703248369845187770258266672690120847655388939930013275933674611834394219417857008342789889476961087750565268987948640076960687145824943420810790811337586248756086499885172169482429184987170544408759197331260068602069651267859331420520029825709978620069, + "H1i": 10729167743901179254947397571313802243248464708814716611834731283062164939419148295193303894466168597283053060586527411331887229950827846180721205988014559599227726488224920399348244941717863349348013076471469008647322478863955890972927666362270829813751967049411057825534018570006950710855639456096537606662538815032653959156955579876113647296248382769434092539329502397505030667693596986208297980350804245291434581153349684336317936833899727476094471199373696306532809047016619134461715693054793867896930794394959253695634618690572820012636945666692937658076478781384854552733418183634491051818033600756607712899933, + "H2i": 14051950471688030264555239038870418821637198585986798721972477949038416709097590484633248104408953905590368876143703728479897341610187276791695545329103963773218679654058555603055350158277255988946312538634293250440297039322109083410661730737920539584913022793678289465433083044324763016386228834389922616917177548121082858862377522424299473290205604975617039395351106270365748539246993156136307219138123292314488748826439419017263340269114026491297035603910078196711807411867099421735700100927832019196199004939694348565943540513783376766826365833338996113985660951898372535607712429624956691170089978508252810182740, + "Alpha": 5404221740721105912513750963186095166323789940919583131231308037059241781825968224159499453867965111118839577975441045067969490122323753119448630177680615468610457774746237626267039660599502344897831941033171086349832385369661434225015299868226007922134291291567685013639571484611864685845173829969825884778866921338715179779052461835336519490747331162725403760923201966927568001130007253452799293921738985284392084621398780151976557998660502449249226725624926154779719610271984085244961479744928231496563837755048178615413905210148989510938131861630402488086277230839157501171368709090317084572694926881626302269696, + "Beta": 3762591094256339699224516198392542173593698491874443519946956982811008467717440207540429621017602743636146123227737672149181030406176970766703235501416227273058287873995624528596449648877236575799971771707516940377656645539659352288953240809409250814460846892947516495485334911873893588253591976131723546963845783144890194694949624209789897688827361928752092002501491290940323779011366753783773075972021051740235975654527429911279174450069923413186430494357504463109526158591234928712058046654935348763771751117588405664231221514799794810665253795512005366778292551662307677018759004997790858122139063962007463065095, + "P": 78627801181523514524115724007926674247851834115005510552808399059821004030674798309904221774345580007205031695223713872497098240252680964852846773699458429007856315621643198882848556651962266582888838679794045065925147268003374531490436313384179786774903226631803394365859890188115488811962284557651647329353, + "Q": 78295467225285502850962974358761057727193422152228839851794623322143732150901579695614193647524356502761045283965640476822051841598305320753053372576908071451831934481882217503860914526768658745704028269070470733723000975445396053208708134132797535363161526311350042573774319868613719058258453817678554644083 + }, + { + "PaillierSK": { + "N": 28965585056747297116093911172736688255709713426956305422466158531528275312753459150153960921956267436982364144826582132223820734033324766201493543258608792234445627909807277287997711423289139722234578296129807071533874463987488056628898906605851893580941513478857922136052768080724011187616251985096791772474528536681272356847547464018608369402937013137384941941679980717947447028786538113816163188766781601632458285110278536324290843834804234907596486813566889336127831055234537556688899837584494639533114269903480724548402705250279508044957330023814730263911766908270895088220157061700559020711456353099241852954657, + "LambdaN": 14482792528373648558046955586368344127854856713478152711233079265764137656376729575076980460978133718491182072413291066111910367016662383100746771629304396117222813954903638643998855711644569861117289148064903535766937231993744028314449453302925946790470756739428961068026384040362005593808125992548395886237093900456696874444861099344780441777149225722858140866568583583768869565007143692685472702842061894418250218457714473113388753624767751880003844864512727138552672844626853825815577526221734843773407250647839341735405718527195533304583667904197221771484184574081093155982852680701638937209482188130445453476258, + "PhiN": 28965585056747297116093911172736688255709713426956305422466158531528275312753459150153960921956267436982364144826582132223820734033324766201493543258608792234445627909807277287997711423289139722234578296129807071533874463987488056628898906605851893580941513478857922136052768080724011187616251985096791772474187800913393748889722198689560883554298451445716281733137167167537739130014287385370945405684123788836500436915428946226777507249535503760007689729025454277105345689253707651631155052443469687546814501295678683470811437054391066609167335808394443542968369148162186311965705361403277874418964376260890906952516, + "P": 178089983473035302674000246538915761766862058882219328198980273153295806644057016290322416080547763839839679075048359015615216203205988656031953111061239654369818341983457655397240622331675270529600175121859916064323060154489763450792159539065687964223092159501524386227134560508803732837087296212506906197199, + "Q": 162645784405572655151265082508570086871699632786440880343833277256412092128193712154895367002110048956118169119801231081898120382062742491556843973480195404652667023997372249660504162809349681456699593485942125013268208041398677984997834676354598756720305600607184390027317139788477413455404680625844039804943 + }, + "NTildei": 24270264760991222657004405633648149979966387612679246634313975223901670711222461444764696178608339331683451105679110737969601535450571798935560415619842438587929618815204459147107864745619438033231353766146096944880632292227040943339429027144922020627152980690541715173185237669304603623388554654697778423258316635313003552560010984673158685283515024828040808281916724359553300353018350848157184280996219984580209773532154969840521421777484077721779465814542849137666216784574417422824936129832031753847371233634301199540388446906147801268808159045744278030696674050941363127582768125709841444653037047482415214379113, + "H1i": 18924652071545194723929052848984512295274019982938722070563008732609366280836333239210784808523125805851433543943555917452070194489074063138181950406806450239876599884303334375984390509936958856508526113118829727088694608138335214999862416365718863020984194886055654025518126981247103812034386816028741382896899250151804912996527753697124149386162473324380727667008121775905235070581891898381434382389353872136993290068154429780886528808028393281178910750610630834614174168891687760790470820770493387298578226183690937957084757622794494597067055242931313950546217090438442846116324563184959096088943547680495838735105, + "H2i": 11894603274887612437749865875901576435891785160504373179161089854225648115414634386611750471331832195938443416923919138217464099139104903233983440460909735816320393310179213624272613414185593602916696630080192799123079142256502335101334140234753590068159460244121462188226522471840465867531477936144527491170226817230219007339634423409724853041690376415265293854098365600282132603310487505111292837244757446147686758990709918353806796319833267683102971707925680089954601184659593729705592112012344383896194374334896432473434922688390913127061987689388656127567822811454578679798507104896923641631902477380066527789274, + "Alpha": 11083001642443217173084093461781951872088182795514707663004408480389822784187218553143886562523907212067087079873553393626338859611220207985278931285329018975932354176288178105053330579707298113179867045575255848220853460354625869605117053923382736559930921295544448349093733462889759493839982576018820711378613439466557625725643086345380035249115215157951891554232000312396930342220550486066773211435739344662303481433336774708543067586945168031086005686057770052117127537530924069856036184262689503994987465332635087624623014382013275842759948037696870886524096716435157646126499038721665569931857777769258228428557, + "Beta": 3859845581311671438195847545641589707370159096982320246346301756030977033141725331248357490866055086630951913636422140759745072187755062155066895059995026509113507695976824677466897180315460141068083431947899428512135321268959453001082414575568451411115221008586534141362709864776391658464432253515900745180943699779102818954194766331439378045520742655333012570830442963566818339899920504289009741333227892074221149402593350368252110290710430353946025817717251840240242156010579011107664096940406800962645669112635284961354536176930649041875012615941598728875406393232699403995916676975040576796711582235353837302782, + "P": 83536423375160133944604276400320250049537944012819589339473016716678113154370173746424448175642921267490956105068039727912047300549643034049912618006274621874834827634185043384766287175213264289003635136193008988742707313099015788966091482798775248698448698500134881577243790883609006801832598718711079282343, + "Q": 72633779914163993624079760496234418186572719972715688420151890654951622201643212647648597949959407536005953720558733385672395062068762798365314735236308595878674280158065425597867435319208945366320733541632387483365747726897341981233502055227314557687165813309613006969845090100170327540213282569892211993699 + }, + { + "PaillierSK": { + "N": 23066293973374406352186341549710577101931792038463326784951672047965044525986774722162218980646526846173276623552222908053887965034734280403404982654764465774142924999612044923519246991537522795339027475867537898352604419105038419596508715903602845214057186360539596583176913558618828990968259912597336382898159585195755714227359627789839232610937086396093093556496714534770691004138903739766654412529572767594649642255510057768084840434426483312601705368376545179699092000171333729704072913188427505485895219155373681969348805237229715420070812172940849661447352091157959526687060051382662483193714686499410808753061, + "LambdaN": 11533146986687203176093170774855288550965896019231663392475836023982522262993387361081109490323263423086638311776111454026943982517367140201702491327382232887071462499806022461759623495768761397669513737933768949176302209552519209798254357951801422607028593180269798291588456779309414495484129956298668191448927587825682074905554022905318347346606018706471426610004597284162329484425396505536668791588666036605025109579653475289448891122062926733987192543727528589365451242341389609952122484603387586065908922318424777282614986538609466869215863767373391601546439196486444061539503329780885589671487164724257578811126, + "PhiN": 23066293973374406352186341549710577101931792038463326784951672047965044525986774722162218980646526846173276623552222908053887965034734280403404982654764465774142924999612044923519246991537522795339027475867537898352604419105038419596508715903602845214057186360539596583176913558618828990968259912597336382897855175651364149811108045810636694693212037412942853220009194568324658968850793011073337583177332073210050219159306950578897782244125853467974385087455057178730902484682779219904244969206775172131817844636849554565229973077218933738431727534746783203092878392972888123079006659561771179342974329448515157622252, + "P": 142204836906214060873846384470979916386483113860696396252612307537264463890091367408851574309071041389934896279633370809626009464905908939267600120051485231739655219188728461713264233620303847212548754272904819687180198121685971720895292202017684896803764141675933068438191432264096052332501921978029012644247, + "Q": 162204707485350355377735594731558001338565869289543940234907658908767571398019361284465255043169652994664526816569736379561048725394720905359720160870002769228534296299826048086563710361348486141528620245619307716938634038324809960743792436176381561550709556509138335169861959556795251518238435072866638486563 + }, + "NTildei": 22506576461085135780362573907053320593408898740606555705125761820734358361453740627473014989120838109574225118084323553343935368507454426684669302206023491673369708182696668019047033262452958436979773813858569395579184556693209984272241086731432400243654026808594024510846724764960489943999117152230403301094930602498252655238753126387633917184116586137639795301603894771525260979076368776316467282412954856805108559047861888345199253349522959422284328133076963926951355456349950797115664974267315451245791810244521488270704808323753089871618817664022829503509291733237497696682114050100407955680454191739465981685693, + "H1i": 6260452569900944861986069131539031932247928540862459626102490631401083814817021939458766230668711472030785965580037879111866340334831309102372548973224351047909263111161588486381672131330100163202665410912852514688149016670996784755111783847086590967866825685876924922692805301002025966569165482864963446903248975382293185298064425202352462895449058650399368234037685789282935730556160720673767432268680078795060520708801163461157592847975799979388026587989697791575773394091946844865143014222257912222960607124020430401385794699560783770448674739707841753094903263054094978690449853738667662608369754317637529877915, + "H2i": 5428367735697510414461777653356006304171002233241323949274783449807325590487616826669713724641244491237749761268118469192904653339552712704003752021300781051851250719602110988020679613046369316736637185174238406299174246052458021700656142467547012085226659058981532124861021046992536880144511978649009016032504307018892231153517765257055932417708662961799065890986365354893822496747288201610070639657723606138845317266321999857712591696598879932681708523361152103385596035928252695126581405009055712536486310059750345626118505675687697540594505778929052868868586478452623705695931386784811468407104756040429603650580, + "Alpha": 9967545586282281564226318710995034008863600084119020077752295545841370217469563411923581063909253581150665826566515794175447025827976296668393845988937597960704759949828233541641044444785261812733022705401670944210559903591234738402705765669566371852585928263912774134857830599636942775701453057911517597738981999435553365233824507966201241278479330893329886817259907411644673251459788461838235058170804521409726645199890341858033632684159057495311973081437839898633586507566045476570700914112409383650753625952333610092481478108857473796851927157154424862678217172597713157128031451814457997071776446128240910030646, + "Beta": 2851897375151777887287799692057159791872897005101288168206880144593456921455592765126500082330530100605317028022178924853038228744762568580551440427037037452286276937035519576052388976388807326658708501473736603178067105670894014905092826262557835731948743111371237147544087437718668031055244802562686276027898439503366867316637014570417307392171091763428253141075588667493271693082411464209891131203973914168912239214932039765651259330358163945601979683592374995701614819184222546916789362915816489276546263931998056945069523040375717889568505019020838186990032151991810029362928731369040496899089507968639022163635, + "P": 74401677442328450333825224989924404588771811337948973919111427142771731702080756949264560971220845828676048083628043971596460231552160748969281800564258760342221365987791868660060002049072411396599695765768131713759938903603382185350716281025477057635310288278099084622984199940837415254896298985445916450329, + "Q": 75625231966479630334429781175990664737352348648745588949484949157310941932346583306687895018681953581144134790622876803868105034588097494867586812661544509629460071813148118329945135448830960294752970752825001607482802216673736764975124746902091656398523891595428191489627017131406009038061743288075377089063 + }, + { + "PaillierSK": { + "N": 22989445036956416909511930861631096675290248980599136583415288658679229692109068809726113559689055380738613859233578946124108469105117381480516877745403859500659002541762180469171815768851880373216330931435441870919546986281620194577420665233873062685520988745670714147924823808673608737348094533381243381638074538770793147019783692509591312857413359951931924621418619953751821857825928220866955523100166192951451532763455151700765056451090010712280093049300172007024798517755303887961030176813282043751654407213313000221448232474846476019957708845960066021334895815046628707259895545301970949083299715515283754620297, + "LambdaN": 11494722518478208454755965430815548337645124490299568291707644329339614846054534404863056779844527690369306929616789473062054234552558690740258438872701929750329501270881090234585907884425940186608165465717720935459773493140810097288710332616936531342760494372835357073962411904336804368674047266690621690818884676659416482719702521453470598007471097759072789601756921456482920896272357734781981161586742471902645614271666999754301287257166038198612981831537493114191220931596960177626268204650050544488489379628653813894186787186699518731958088864645135715220462431115446344483531025522064105154153724098136138132938, + "PhiN": 22989445036956416909511930861631096675290248980599136583415288658679229692109068809726113559689055380738613859233578946124108469105117381480516877745403859500659002541762180469171815768851880373216330931435441870919546986281620194577420665233873062685520988745670714147924823808673608737348094533381243381637769353318832965439405042906941196014942195518145579203513842912965841792544715469563962323173484943805291228543333999508602574514332076397225963663074986228382441863193920355252536409300101088976978759257307627788373574373399037463916177729290271430440924862230892688967062051044128210308307448196272276265876, + "P": 169771054917407652962226785802749500087428460061196252562390242724494406164659032532137268081578587064177740400630697028859412105258742820176871107412103813455640938388361263814771098606761817135307957105317642215837535726246229904774779543754071776933374749427860484834662728181775123641887251287683676674543, + "Q": 135414397042773927416422816847367342383735973725149165342386798061485659116553718770855931845102662081982563819490455163303069831499191494877258278813081965186715716173022268893722668906419137639367690850687730217237122375201208651266751572915722813960596203387875533458170766076067615133105016031327801679879 + }, + "NTildei": 23908959017056763196840100500671300836099792532786399124182388698783878770422903608118315683994247982561837480742639859126912515625980214150624952310740847821394244765940541487310957790722980060608223708236470994666396784469869130897343345578511927471667957281149608903334590846942458270028093567484863983427620025195519535151885333977737970180831319913278581177803484312530861749246769316991953742029493249408994893815852931548788596710792784211555741928349408859360556147206033843299703107651460682301339873758006292633259227809164753504123907130131438293879935585068951261376990332037082026934198133279193271793549, + "H1i": 17882467143952385882040966894148518186108717498696685249815342728950677238846292891592182218042833281143558428260868386097642649171580733696537150344149856045308326728288293990433695036194770575200134942949358426796354385901649518067341048738928594056227751837467337080971667754708008761271700916390444070536938903652317329971785703659006271308298565006646007697250242556555941225297551634220583237437371442514257394811924782273207792238045411785301670001851325640850333724170331734997095936868890832249053012592776972581119421521090201792821786056522812901878263191943579206745712351326475311952391849857177559621297, + "H2i": 18737915933081860710066371006297062560628480807792777063893418598193828197060179177464227877833024392823615719570756743703392941056112536386517766456212365200351744624622518102897120178332649478130918599095825223956914879778709172722493105274188101758331612604513750431399276505862384423310643522880710158991380907652635704823552898217362281134172191556496688999197505450226667137467853554707860446517571235589124954625369340480168408629446687492900423895984715662373754485729441575723180367057056932006417020044761729096965446959894778576251216599445306737184728496777595968143501704089802309590961040116437619461311, + "Alpha": 8029010711264237208686583647164811968158109425659057631367860306210590890623119432415309662798781640482188678544838817593269712185079492722602426167492240877156018254541244728892281478095724002607411195562643239235702432408238886235077843881558249797787905723697276062970696603107577285204669526077361752040315577604357447557396742024852082524293208840334254799208440835529109326493783512371414919105746155679996258796523494294334915910787424795481466007638424760616915431846787352565926043440925118991103886150898509271429364073081146888850567665761313763116256069151072709338326658884353916402124663190551121873893, + "Beta": 5266530113852230550084288506942357778691967251762600372851114571694954288918262560413567134536133792689461450400759089249736806618812717224780213186826561365227548041636574934133158867728469027778313540696533575604791658277274504345054810492517983709352326454718436618455579063089157985925626903716090918233597060085548447293449899098634144008717083049265699959852834427003951671001941225454538680440660992539657595228946260067521752321228638737183558034532870820008313632780811853816629669187702528306371245172088324005252163831614572748692639409538824885646374636346968627341895205671671913259344867806280528775399, + "P": 68232747950411669962652970993155860905862700905775823133260425975438499193246191553833963912586779485845595811234597863233489749796005799142950619180075163950938951690156432894105784198836346071525655672442792154362260783757029572967879826660051745556820890073203830408755437609502433804490969668332313132913, + "Q": 87600747937165971967546408684812829899799440910015873925541451924721655618696199203729901207420601045307411009917597339120480990510035294907558138516720743300540353168168320411523941481172016365543477632760665628341857807274943508542779881242975342056086928731802566123136786446510713191460150204007187907943 + }, + { + "PaillierSK": { + "N": 26765820551543897350163804684120203611767570827895919930248883774681078604093003345641475424749118937599237260909231273866120939177939212397586016268750790898637592226463752934694737447301816514945227536805037447608828531724637996388653504310207845746832173254695954514765072728311968373508687925080640533054426412296335272757447560041611479373492872516543101110152781041278827083170506661741675786596829710705108091026741065542289487396917245853829391302151305432039427361327415332284967992658183426259780273089900413478849362255510816019715686834751869560208565218599855638253832741610597215051301526080396429673097, + "LambdaN": 13382910275771948675081902342060101805883785413947959965124441887340539302046501672820737712374559468799618630454615636933060469588969606198793008134375395449318796113231876467347368723650908257472613768402518723804414265862318998194326752155103922873416086627347977257382536364155984186754343962540320266527049448824613845252708950825822164413003248484741909505257794559199424792717575964507384811026910214360894511945852411785069577347217126262165352387381730937278966516422237910791112520584267244187977450916267888649540090605380683126275762889855110387401131865233643659771731021881930008091480412322081652964738, + "PhiN": 26765820551543897350163804684120203611767570827895919930248883774681078604093003345641475424749118937599237260909231273866120939177939212397586016268750790898637592226463752934694737447301816514945227536805037447608828531724637996388653504310207845746832173254695954514765072728311968373508687925080640533054098897649227690505417901651644328826006496969483819010515589118398849585435151929014769622053820428721789023891704823570139154694434252524330704774763461874557933032844475821582225041168534488375954901832535777299080181210761366252551525779710220774802263730467287319543462043763860016182960824644163305929476, + "P": 170873535042858644672015112367556845333308351782962674316538868671418403393696053449264165680645895942307218412402552134799276491754103316969618760732878190458609230532121214715984216886563174667909416408744874652622452067179821994989047509221114036328438271455784773366073120776653463549689768989650030081379, + "Q": 156641112064723607357643277599593702153067195276319425320653054208559094341658679277641998862363386041011848722633689837351056210728890012529067766654965367022885097950818295986758734603085763215915954848619761527146728977569627772175113545820534749077863216676783545344297577070083735318650932446583093662243 + }, + "NTildei": 21535216757910549407680652104991801807551277821055084749898261180018921057967636682937326967001885974266934445470164566163553732402426485068937055885157884708107831915860874810680005899953177564575487854629351264636545200880690757235397759323301186544038781945176364835920119391443419946383219333711036557841708247979735078519195169482823973602757945096038817263412702253599235896703447603256619691872118562528302191558980543606822832121806758077560038707687782823024946740773579460460970576836576510270117024661584885237990761267145728081970596952824870186296634532161287048494225568514145454260485164417722017896793, + "H1i": 21340670561523059716714679892057139696102081845076411742073308478175512019057433841906888676512301543029344769157325902912093412672002250609151728967525088397879718766102464264091937292773697463541295569254282682081929334091552681140741079505800568846622234936404631021987134008946473208217239006561232141879403697493568945888342789443194432051100416301453164271313844958548955710107446304392223480341642354859909726436657460664886990094300717377570533702592026898325230973796505117448509565771136433009258355312880363938146554183496817226713643772837984969509153987532816083365756360269771784543463473764060944243393, + "H2i": 13164575966821088263438901897537863320373518394966208936536975677566631223422075091538717744160572133441962088697760963870642029503024131395481232921526592944247151993724594158642555504783346759879810897248479733393877069225462348057220808768721910601698156669005707643224776101332680989835909583347649126824215664135071363956333682309690096980558956164986302308517018668980433767920307853242317477059440702714110835588983808755685957568010756232365179714587507580062180436884413071234372470386180255662004757448151472324051790202063990275025279749843645233943896454678645606121324427758216792679968642250833837022451, + "Alpha": 4741122901135866343734035968261216533299139889310150743871178050618780016917991471029870599460325444451446366931347528269438181424672009403988021341149559058405964789174777944940347112467997878214445395958730711319677224087362722715601309944515885072678648568319953026859727025013755163400799943598302587797619521045428373821998818732336930435792003924457909818840492236050283481389629761678736694885154581881963340113982275964712927927823892023585845582923335244452249647203449801881083688371128194342032163649397094160369179716214006246906476490222544885722116723296448924937151632197086065323338866794652638262125, + "Beta": 4377569432115155803632373136702557600511335610724444737091619667151201799095868112516268189439997769361935720666061035567375096193579210291775065869907741840129458296507779045487185094340388180900721578622294332334818429104692182226234836060148685434933536361744671874942441606467052199097948571591796877320386173357256853058743293752500680126122951723713406614386042089262190793056951119546676199145659647794684168355616755316128876117520636496321032211026580793619694728671215882476608943513208995020073331403901398034589854011687841386189919106692634020573295188612111825490367626856384226335741525953032051282385, + "P": 74792168777388935395178730013196691446668052746571217774468154413461973944068373290364788107151959411677218343222264053928929503055372129795458704316411680520743710203524086512404459207465134029657625306915671374948696444813431196721518303300600096809172638012662871217393817606582350210933892633261852533033, + "Q": 71983528188652573988157425749774730762044474753710674797659187146638747279500156667711865807131823998137283049460265398045345109086649250173426754634760087433898030993624550541338601570102023448417819920414529434229987267397129470908794034071477479756666896618245977858369558869334273714313977016742355766289 + }, + { + "PaillierSK": { + "N": 25178264119956391501302431185322476925566669775715319149088407359886940712517801902870915488681891496938667797663046408577082098920267076618528251776509720113409584497412945883175671272725293038698239248980784084431763030186390276676851313274068674432083515777338731141832224684969656435651219991361946938463702999499495989179181818153913120069181198986029890222004128052789345911880962469521185617435442014656230908752245657169216504019102335403027700032222188974060582731802289369613785156464307447861407510598881649065360032120123341622650192902300882521607632499071726985622566202695236328361204282620327759629449, + "LambdaN": 12589132059978195750651215592661238462783334887857659574544203679943470356258900951435457744340945748469333898831523204288541049460133538309264125888254860056704792248706472941587835636362646519349119624490392042215881515093195138338425656637034337216041757888669365570916112342484828217825609995680973469231691745833211228102640718140292067226272011763558951440785031476331402074439026993310236047622933453567764562025615230632234776315124465840549336047735241699694087072787414954708494603780695696685319069830147627533742792799442507698487599863343818273164580506787141198938089782305382047189324175659997284779018, + "PhiN": 25178264119956391501302431185322476925566669775715319149088407359886940712517801902870915488681891496938667797663046408577082098920267076618528251776509720113409584497412945883175671272725293038698239248980784084431763030186390276676851313274068674432083515777338731141832224684969656435651219991361946938463383491666422456205281436280584134452544023527117902881570062952662804148878053986620472095245866907135529124051230461264469552630248931681098672095470483399388174145574829909416989207561391393370638139660295255067485585598885015396975199726687636546329161013574282397876179564610764094378648351319994569558036, + "P": 141232314854412951288741344440600598525867224473849957427494572063208086011758485559099733430076118724049208078369916754814067783739274617532881138703203529253949082728635792338579634400809782732161731326092289322710433308712417287373286830918670535945520837917695914946493920340485421957473826159909142801687, + "Q": 178275518219120022611640528888385018111308234438137383006570528063333676991149997341613788759498988796652576622645279149932883605114129104396146798048502045418459503498823667858216314502106271758607639612494104675164013212525908938301706344694575439332950647579748672799892717743986812025082105140424047269727 + }, + "NTildei": 22093877887323493169549748559393057909033791772543279348241688481556188488900890632829245355662042125251830367334809071172991693975369819747538802621003015252984345165493375005789675251854355419905641691081015932728893097825774177944288712149754606255347843824540425332322900421600658104268269791653410976478688673647065241438635595439820650391799674980152485056735062546960385902393954358363241397528585796163701180117486993962035242477759328926996675358152193322589480968177026602230816691330731185765282004364344378690926143070762288023595848898093804741451072709811521815729714120215612110188603117979997118482217, + "H1i": 10787212679941641809601191414313539823473329088857891022556713155885619125517808738288420776581228517199035138832894669919005605699256105922280646348171609707303717972548129019434115967888798670636803018742891021411182569391514530236168484037498260723066697515932118576624090666695889326914935975396729037761447145248690281131645065206104282779862820515835614876750793124068211592242446551011681706039386651673871127127695674498186329425472900666551366610319138331310671989387721019032536479640900365762430296058557059661157482915202334500084411227035740307295053511420284168027002770608948849568515408002695013484785, + "H2i": 12983456646497293048459386805988751371784093548480732062266527998415459154204902153349102884422492355950552147546027468676863679687451804982680623369310284548962742153647076797082075935607196021176948631285809170968109630129996138580085372395180455835113870919792148326844590754021986294211120318271095745154687512045967806106775314826171341743426756014473124971105020911210317569477585435954177869307472975155515320552462260848314341223845094413975357890642173840339941554869652265214427336315821822368684394831282890596118476432629501143683404589556051014294172470677415700515137500472994765285289632922505068595110, + "Alpha": 16348444390648022260576861173231479265125222428400039551367444094603385630036305519925577659461919281670876752456758856295387743399143513780101257132299227715795651740969138108206684914007049753773804387271515461903223715362047221124749205687457652472449645592636044853262648933883649664918358548015514074390338778848386201089156989526218967918600016449283601785726189976061094639643966297129686239948509084627659989235036357389931045756497656613484937633297277631799945745368376113194965614490147946321788669727307583923306834089739162949772474066938583070038744781343325810767575214387802012949848027522011584524584, + "Beta": 2872351192394396685009108828172134869658140473111538075567365532625685759709958612064732895046807276292022698445408564619544930043253117566983721779118027242501141650538020180132000410980210710808215482442561861333462777174029633755154580069312654396795284260138614609500620405836174364373757616834630322286880027189283448217316405634865004219852809578498658328368710436274760876694570279266493403562413431665141843821413600670725841347255046089784701276167042856626873678103865457759149049977088342993511813722221288897527430862794865188520720431674803818009985345356149045289278004453952157021317355093743983049972, + "P": 69474716566946986964924139924417238116031979870041444027757813909331955272292840500155713585445071289925928058281494020145580020598412529062145849726012319042042948277041979467765911102387157082116604029323513409777698083063297961633765870727243404241090725327756863710028458992257893756914826243891404962561, + "Q": 79503303428497857549247896356302566759492812579480594738340788126814754600912605706180515286898005890948971623177984045958144558749327760100352543309574382772943169515084842958429076969938396454388523040789612036915287036500820123865905116323836004697891579472041653173624994744713096938163533558742398666289 + }, + { + "PaillierSK": { + "N": 23242194730800649656775200775540233202675597323866807821706313015980817450049689426193336450806274780026072878835451600458393952610349663564208170979818834827262822849655743287789154279342187750060682752334039354263591137720448845069358154202631407620757714837065929559179966203904720976823170650636059524399487135023699742828188067812609881790872981276464173035759661249804017496513624359705026039406647066008441300178105916662499940466664812327662278750032108436832069341259004799143733233769086279020862317902253734961394631758425136826181873168564179946601945174693635691331861638363238193163336605995426029296209, + "LambdaN": 11621097365400324828387600387770116601337798661933403910853156507990408725024844713096668225403137390013036439417725800229196976305174831782104085489909417413631411424827871643894577139671093875030341376167019677131795568860224422534679077101315703810378857418532964779589983101952360488411585325318029762199590885894644836060833715414622258462706817432831232585965890146122582040939199695235793185648746653119640676906156162984365374328867849324998076469099333686480619491958071127396703798142500350403478167864704569445806514718550177186286801569435905992599794756141294917389135650522614192718916848672778922980402, + "PhiN": 23242194730800649656775200775540233202675597323866807821706313015980817450049689426193336450806274780026072878835451600458393952610349663564208170979818834827262822849655743287789154279342187750060682752334039354263591137720448845069358154202631407620757714837065929559179966203904720976823170650636059524399181771789289672121667430829244516925413634865662465171931780292245164081878399390471586371297493306239281353812312325968730748657735698649996152938198667372961238983916142254793407596285000700806956335729409138891613029437100354372573603138871811985199589512282589834778271301045228385437833697345557845960804, + "P": 161017173667821622526367617864622003641385319273501283614693369124550309525151657359747838200440650092833079350446346094169824829878819721139600386379869940529163684111577023046210773279749168464606353391602564223720682758771657549969925797763361964668478535547946618675375707846699109613203757337339941079703, + "Q": 144346060742249083994269365500742861817961091528206580213187588434303105110073311873691829908713109676326867015347244599599366979050293956526525425453571123341666673231285521304114864204336409749299628781242031846060919562553124903638344231929005996733877126863099237878214629471310698112299151312528242255703 + }, + "NTildei": 24462860914747243358546323627773893130738821461401341824825345462243925237841933489180433891199395008267429251149636383024979936914386984046495112392151948885544779760414274487116095167246110037323486328775942623587631571153493845894931798269850622106468371839027543105629096126331634821358789234665535182945666599988218770972852864020832184318539691824562743434286230496780946029169869753200212210690535339313505927461656422073430532804915842999599806540610850726389802813802480680519030898530064347299714692209312597254577607740946972333057134302610046801192952574149824526450685850521950623765880866110076566808773, + "H1i": 10050111706072495243999496814680934124377036398016766556993758397032846983391590117026861690183428233637999805328375188685263419492872311552210862921880845503002540327766791640270684615415947597129962552492005207123808981384764802739931527057423910433055458939237948011685306316858844899288071012390694464857910925354616693246209580514398844488923519402427095453694346379538631079523863618523658407665895814194555793056170432586464435501825929495088772006175959000483916365805823515008461754920046768389524079992065653925518809116538312674411234999450853578281972475545603447208689386435339969834138106028771124890635, + "H2i": 14240361168237288068074599143247216646824416105247524598385668199928133749956751997771381993727512489025036164585045407905019041308063588759262145916854388110347511018859896750235599397989884993301952549732155614736687037650588436806998093798295537479731407457538523629128380259771154471333514983408120325105539209719539410529069810447354248260337431660473458445640003577244952970155697124223326049194622369634632061010178070181535453197753358681130352538997272972246700803314895934758789788841088333414449403623275628945443653201156849591802964784565324456501704948791001115823645656236463536974557068156273049934353, + "Alpha": 12973223416718265276543094319597737135880817758520547699855171994913850577229036245561142342726721549628072360908078370842222217964111854036231190108863701396573809741718032125380884081811136268233092886654955645982113169626570931827244124008255043238012586786025925483487628216501063632074260311533680816475001345643503486119583369115522487989683748783410663423858506424267007600167043387779024928701473003243349861105266523923145117533904155246094123924083246080334683568210381176752244741844189601550259087688101159063321204217058083328793722325268822386637638841134115712903942485806843125188547764440697352266825, + "Beta": 2933550949281255715481513143636684273688357098271118867477676858128493782213012789887202985438166017438239382789612753878179756385192995303788146369289283263829317774531152568184088959908395537023984533674841281596186257303870883742985602401587488297819239875766225794106378648175007552763966126326983323720948105327353286198373302884085788309479875410221334578495667848070023630367070958705395075434345556214450557022277297979853380022975824660344315262103406563445992104665285416934181640684387860701996435030233631156121170487201036480438734770024721522421204104663883737929814082819064453902100974781489291368351, + "P": 75195193317352594605418632095719173223048313126386625279081115009963743580498763056456916415080261162715744114963810511041266297124242372748157905304325970559141290619318878369665966113184287197172315656924959104034607032285007311010185478343102575814602672742613634807218147433069590759326855168152019299789, + "Q": 81331198962095141196674060681595439137163195168077511727355741071870348635329587030619524845839731305172637610043787212265743219238365518057655490485543400006043356343800474951368642919872241699442958368914028317022408399288319598858952988073802103260724882216450798170738637788271032928983885765684312531343 + }, + { + "PaillierSK": { + "N": 24635746882601051472177496856996850384505237002204022414903626773909729361565597854418768496816897940448630169348253277874213879216258404131130555697719637586235056419719107511396508095296838196442120077601043489143766924337782639383616462750259557656691164667888859967526765569771446730344677629914523316000444329376590359887784252246586793925486791723243543747893784208473717645811502099124639137662388698917992002753974586389214497867816838996438852946560228162243317931420827422894813804368654162447789560903699783851631762964891176538877308742405247587933132559389126797717345505900863655908278046332908315499897, + "LambdaN": 12317873441300525736088748428498425192252618501102011207451813386954864680782798927209384248408448970224315084674126638937106939608129202065565277848859818793117528209859553755698254047648419098221060038800521744571883462168891319691808231375129778828345582333944429983763382784885723365172338814957261658000065077562397884235470030028203033538770995716352181372402086470166028049731747261665981796338208761902029142694509382334388582915371355608058899470305471777691762896059281154266381723150220355806571679654424667288517875465849143025594439802987991549567082226031398187829943889272329543844446572626859268896378, + "PhiN": 24635746882601051472177496856996850384505237002204022414903626773909729361565597854418768496816897940448630169348253277874213879216258404131130555697719637586235056419719107511396508095296838196442120077601043489143766924337782639383616462750259557656691164667888859967526765569771446730344677629914523316000130155124795768470940060056406067077541991432704362744804172940332056099463494523331963592676417523804058285389018764668777165830742711216117798940610943555383525792118562308532763446300440711613143359308849334577035750931698286051188879605975983099134164452062796375659887778544659087688893145253718537792756, + "P": 163460369974826440705514174662949009977520516439071329942857631105315772985436382454982935507143405068897778874365987222405487933545534405214049775023862225745666501278783035529245783452075153398271280683418197034314208169150226108955250172348396091465939663092045169745405438732377680629223383632171123855559, + "Q": 150713881819764976138678015517777837967279774100109673146753637036345773362571193337692609478827770045035938490589834498031844103528593375107004230925422381114125638023482078832804574616138297436374920911432252240281803864042664378733178964080868397333028444234285252312052288623826887590161517447018653851583 + }, + "NTildei": 26952301843143637282866149797084711499812123886649395253203935079954892716635012287069597740882929584147084078842102570305553223265651965517698460642753993177010911803776480967972569645061058922407332007731875727831446192019223485471387261222989425576723278371943738118392001189004304385941489228070346488712290802294597234526146756924141041718603271884504366484309043350924922954983414281221634138039891694805025219737053771766703067095030206014515414216099919878243255679194598668517425955488139864643616192529281487814170910272949729936744658193229259410265540610217896999483463791982710441403248992753863657411369, + "H1i": 7039533162678942927500209993292727850895372009485838787575679546863860902464664073719022554280663741270495625962519994057947786404908609202931303662491477271027538713978445307424258608865385413013781216152813719631902620102779316387787835766065217303491718792291591533404701933176628587632697059792054500151533149199882139659970677179367462465944610816625277899265889982254821608070987255987429355647021736573111167091171507360305828055593375272217792000444689910177761863974036143475753661823704356235420861048525859753242690687643212000706287918196623998213842967590811141573146879354921569341703158405719731460064, + "H2i": 25056022363055830086822505385398905640575301517187597132837058494444904586542165647523300931483325031880577675775864117380298146643596144843990690220614817945554655184013561868698200009014927839618305609934079450880264477839073883338885947061375684387326992423507622720321261448327980872523174098136789839877017037206959048600120659834867005711879010652652441112014458314580694970790539322546676899264966120324026586625834126750837759913648516870020205959401619613107702595243280970598378481184131588087360541614329722802690843591943364481200105690059785415903992824039861740448327355539277969171355642043227693826278, + "Alpha": 15664436892783907188077716879684694624426368673157864476047004218810655998620670324662009620479505310479942676230561323041766561120292249565945133725696166570271772367308155125103790171479966945084747038748256366590448781732116350752413555318512255176345249630587133904775573878415255401454255783977147877542540024724057239467346873433087225801690631817431819963995822123795597189948079157940904783108906698371904613775376721023811020907951741244281932220077795189252118652049763841679324405046714901053752070995206345821385282158957102974070078862166711552246002897702758239522873001347706994897109849724684946339098, + "Beta": 2665901088363227302312160352770848138951599750399544398720637659565888342084078032138667638819567898903633960258303523587749718496504218328479167808708194108430432038094476698834844369592494746708900964366430376771787135045596520705846637874211657423605969246466726662587348957905895144831343894139022857466113116906832849068135662071588087132469701327626138826371300483918095536540048889201637003004541195598094560941923618402669220881497138479606974435801658922631185398941360673587933642704496585723823436996837157686587331185087524635964116445030834015766555863972316746092025819742143377139870451085671520967415, + "P": 82256981148897906812181636333752857057434721490890552129674637147931516066621458172828994294723462311979035516250324201776030104883746041922693838599992462232692987148674967764755276632912586768422762598846491981097374171851523550935427322526022029404381011551880837679780993794782816823463228433498352745401, + "Q": 81914937391015439851158983714133849591735046515490096603996072190891464525166376330908753495906866396396755293430632803693666906909670706240028942243581961947168945387644645074808091484110365503955461469885064872566032315155842155302882993810901636840036120877241302495604535256258694951572367118932901447161 + }, + { + "PaillierSK": { + "N": 23651352943103195173266914781748221649604716487840332558457143873843925264041224010514764563116414981677513379015144035964456499346239206009846091918289572027532360384577201131123237726608102491162140305336568906279953131239707948688758329600179062879824171079558989788806671518219309773451259705788898608150977599663263101105169642829991493195154274692835011044905982753766409942009874621439471731500080479353114522969648877505524180210115387522237190430334703425445214365179078324667336138966845236015234614682321336024368804910127818843797609130423879118547237103373273556120117932872585572665449084450944107179957, + "LambdaN": 11825676471551597586633457390874110824802358243920166279228571936921962632020612005257382281558207490838756689507572017982228249673119603004923045959144786013766180192288600565561618863304051245581070152668284453139976565619853974344379164800089531439912085539779494894403335759109654886725629852894449304075334898694302604526256780475238711571025095421814000468943011217495979892291448642857927283082760578521803898927533720961469088640735761549580504592731732370711512136038487971859913944039400382063386006600112015146759552170682603103595141084978760624183291976897018919998749623955857788270147103951485064826038, + "PhiN": 23651352943103195173266914781748221649604716487840332558457143873843925264041224010514764563116414981677513379015144035964456499346239206009846091918289572027532360384577201131123237726608102491162140305336568906279953131239707948688758329600179062879824171079558989788806671518219309773451259705788898608150669797388605209052513560950477423142050190843628000937886022434991959784582897285715854566165521157043607797855067441922938177281471523099161009185463464741423024272076975943719827888078800764126772013200224030293519104341365206207190282169957521248366583953794037839997499247911715576540294207902970129652076, + "P": 148052451319258990481048468792492479234326478860827126083914804819421405702344546760937235528205817934300163010595803118754422940596655500770241015904699291326992652764097878200911230954712903198747375707690263703976654598820758744508484878100403690458641709642163444927967024601056533755230402445600058035659, + "Q": 159749823338633062175033410721577573869757370346182980936045513955028751724632788962679929806353504375206562103985632463831579988047208922305940228966539392695197440338004502746597019933331568689715225774407042026873045969941853892098842082365954179722011439937072271194651660359813462369924474102373919492223 + }, + "NTildei": 26045394650152182790778621204514942077976898328189874668148855889269744286021446955036937171968654260875327430903960310446359750539784010286051650827824472538547879537966937566144137364890682546641637071263139698804130052289758243894992156621922152051817914419226738457584644213378352547793456576635860296383034738776913137567440831023701130211377981296513933199548055530672358988344822920856996660808938127789821947721226412949736679725523690334009285499634446982731085963181736273099785033971191465868401380101296271065994001114076107675037814092348546554687910493793183024499528050710942088563420877207702222145337, + "H1i": 24959911197791474689211029465596415507814873188767131410439282910534724899676963445896827387808986385756230519782397491649071384006141853473321683153259736359624814923997027029410020129705847253599303387273142093681392114734190156164784136706623340358798889577726594472406258179404908139771525002772733681301116338738029360097131122891080307723515153011439660255193514116009408957019681897041936993754830919100688997946077369053330849481051956890935351244703965969048123920746262964543341808525935412526697612077342868245778516826204312718956152025126512285626340738411580280569640857119258877427339852354966820979279, + "H2i": 14196943166558719414187702205052397976834393774062534830443469591062280008813931827308005860673698786604716372024846752281316969429195560311190488129945120017324679238629646479033721762193629219605519569537508792582562431772472458536263417785954730527119764472995926776324769247285082698295114870841420387956389802246714872269592996605604041583799299136915436423124692175502735276360651454580336279756384602230577930003578116996621826392485948162931608555605836458254888564050076695195816758694497843995986061565981454574099204619762230572602792486678288833083892755568745345761436614848096747962859586686569659899757, + "Alpha": 3703953294838301514991916984893557414618163866536327933615268027522035761208678815276747692629965418925523857938314193104182439614212718354689700419956911854034597918114996413565895411830920981761713126602363455230847536520897662145020727224256572591715411400535497897764032530924331739064799461680124862326554744128175562524014240679100339685181948936771580496987841140319022694664395062277798801960146333144218959214846288137008238739227636396185582538662812741797048409746474161243534986116724055842771246714168461881361109960436358504312692565935655393528180921659921559789208879383644507042901690768300420571361, + "Beta": 1099192752500354711752537437363414689152478490644220971702185990436845557841500436045555495873214838477669168817058383492000295618267978034429525445827063826497937359184484261016606590654673986794559826383598356758958009961258413554131429255863634647682823332395296277833700374118155253728536620625384456343623946415929450474184430187522983701735551222961969249194829847035018174740886698139080867651219652657123266725345792804795953714563345027389498163129630849857198000161742749740309517144949009721404757661215826926157137549372511903625285710571046174204191898516079047257428672737709573414412607114490870889064, + "P": 75948837034979782857551741767588980177265204685651583322702944251384509329113534044754135015071634837710267900297555232712435000398853159660421105216464080569618475889659743642440414003719647799062506511168226089486875073041680515393344718526520830419835001753813253763240392355055242429001570325448245110971, + "Q": 85733355726554595309083342714406348886387911389338312961962747076348057175832156673436744084540651764156389058988990952820393122463235567457674077536057489474713427763623277577016215624190810653491515432590235500024277695157685887232690276889298295470493588155574288267770253843169446762796449840380512357479 + }, + { + "PaillierSK": { + "N": 22209642363557248819917096497591583078855644873537092684659237570950005487071351730138698413672093796692876071510402125173878574469041669415872539252021066922931069751625485124067920384700625846093023655894231287715730546575691001958194456736027522822603194778614461865346051486201736750103274236542212514507014172187592959443541680966314853321816437925934052205764879462098580674481066383717135260818045969621940405728889833930212849505641234939638279612106030540516169327730638727952934041190688134430079841055862681593838865060100591445550085449238428175629135314406327015470479885177628441057971831787893252607369, + "LambdaN": 11104821181778624409958548248795791539427822436768546342329618785475002743535675865069349206836046898346438035755201062586939287234520834707936269626010533461465534875812742562033960192350312923046511827947115643857865273287845500979097228368013761411301597389307230932673025743100868375051637118271106257253357638817790122986997448833353259876141206826422440098361711302304103357046184501518695953908770534495140685218546654756861764836739445223319673611685412410607524854758789201081613484428290377880489535645135653057568789667880714493255341340573451713126812029725324787380599239666055398099203032592303410085322, + "PhiN": 22209642363557248819917096497591583078855644873537092684659237570950005487071351730138698413672093796692876071510402125173878574469041669415872539252021066922931069751625485124067920384700625846093023655894231287715730546575691001958194456736027522822603194778614461865346051486201736750103274236542212514506715277635580245973994897666706519752282413652844880196723422604608206714092369003037391907817541068990281370437093309513723529673478890446639347223370824821215049709517578402163226968856580755760979071290271306115137579335761428986510682681146903426253624059450649574761198479332110796198406065184606820170644, + "P": 160620724093805862596409231804750427174716115163084815753975737643031519664995214399428994461475706604470904139763392748325054642497137867986551259350459644790756673468022513807845438307440915348175585414153008052985104805441946545743188771641948635127335321511997041650679671627016510924638616327627426802183, + "Q": 138273827918907606950374067803583142359308157926087193287481119847342440723702166280314358539029194027188131152033131668164265189665206625012381129384746074510362944745037811981861634026666463320925184351438367425716180918897215913296213996449576114248175933443680399058601734218501133934927150275659005634543 + }, + "NTildei": 29703526264608072178960188737797514280510964970206681797854189108356168805091607153300080823980668286883277325786438078696961942400895679179350081438490115544469019183647226458246380249572189433233549203545595036901800568077206767670894474979553971412404930973040305339781753457677415938896128646095998900518698019928141579731957342518116842552213229575128106810795355943233351983204700431310193268553895217886168153556298116696329837650966172966836426887820340228980651604429029617462913526155290087185238682939677780972756191205419189880037401764203590337214313417437508832893218167071375080600825313170014975949653, + "H1i": 17291190353490564634995940629862526503367246813917974520603059293027995721444868851965986227039796800012584277095282533682294057043501899189439972858754415722943010280075897701325567212327319975896003941997353162959610234200453846231565645701637149465672078877075367697252450283397545667977470649727680703977148209958779215640680587687647623108241285695872277109911965075999008820239425588819079675780617845606657122385083776897390496702600211959384348067494050112941917581516759622066144395695130705033696999762687450799799051398470309426516757897602482174599877270142828798058216642176186694463360158801629844477595, + "H2i": 6335871542931615617990526691318607172232243668916853047915918485835075181896310556624213658848318149370008123430692494300766834429824320521726964826508444924583654512841754045540667170211188624728143905819827111460662612836211442539169605031426871365265997579742042774535135755922090116707452043741761934440789376373673508031126358023383578340682076631871908295857440809378641446492255602557259905694975907632060748165503875367764936438514938891928155785006065148986822026020332176607336473255054848127123410842349827830744239302903974326408421999486899016753392382744211380238407831318581015207603185490751128038819, + "Alpha": 6313523374845653787848653008919738566438639165906450614476217315411888551515719578607701028004011653520456322786688101158769160594837055717499097249430289709776508237118697328227204146576993169226626429252711616441730302615612177296849216559652754906753498477790563387471638184629072478239787636295608254100113355156384613462061886559786499912967447002442462835767461549570545722869656514693641664741176175967825858893535570546168945772258154594606755177878789846863392693181470595115420363894893633593407463799469461733474366929603779853091745006107877083882852190071090447301301741716415530518478231284750808396014, + "Beta": 4507160880406031411213316759148187329401590932594197035716984340447728617491534623681131184339969720220050536799007023898557665686650838464650481873798728860995502189375681527364039268931195966093628921186228042343132190468870036800450310901148773199465954330897683666470438000723062710172624610073084572756719214921239594600384396684505624914133018192260295964651722907093867497261987325279858282622349632211429699463015050713688175368310605358022854133440730984366735536020490956948799420182029196732532158189071059929154710826207782529928763276317934890852252825605572878502706391129823696778800727988104310311206, + "P": 83753826644514129976337808758305334048078158827924782576149724599385507747355035079620148238094125272631100166931865050429422183579166942324107083210214427886295488404836328859173260447800829670929038543251773518799821869085431114319381498563180774506945830417874588013163951742656738393403122660881026893789, + "Q": 88663191446410320989173950348192311373189757091390450729026858450923834341976401536582067033542016209494118343990544753108437843214576239681722036691526067749302941262487401612258810583984825206751734467944278606692940502976259270923368889462670618772210425398607090721474915267134848280210662950242811847703 + }, + { + "PaillierSK": { + "N": 26213695928440677705894825772568428308723164707347446591680826336537114495148015767834132013089456019186844139183289408431429210540624476649987553139831703766737157273370693064614988113888688047207689279532192211376852466423724690103744692478804734865782481702992018638231801781898190427600366789689988690318675537153417157561465065413926250235993828283524059611594304890086216517992913177618795268773219178906809815387465219236859200407212913367531284904246010679294124087643681176345837528548896059486364621508256602534933142557018359766874141612635384710781097169305219572525673467778647112933535000370146791254253, + "LambdaN": 13106847964220338852947412886284214154361582353673723295840413168268557247574007883917066006544728009593422069591644704215714605270312238324993776569915851883368578636685346532307494056944344023603844639766096105688426233211862345051872346239402367432891240851496009319115900890949095213800183394844994345159175610462696554722285348852481204133852464329120648121892679239930803848520227423433695454596966134424048601663676576255265086651818763189313601805305958739577012864096137797513338252332254958270025050743147382283971541739710823312495517263126329243981174884705176721157387105442835423199577585670259921232014, + "PhiN": 26213695928440677705894825772568428308723164707347446591680826336537114495148015767834132013089456019186844139183289408431429210540624476649987553139831703766737157273370693064614988113888688047207689279532192211376852466423724690103744692478804734865782481702992018638231801781898190427600366789689988690318351220925393109444570697704962408267704928658241296243785358479861607697040454846867390909193932268848097203327353152510530173303637526378627203610611917479154025728192275595026676504664509916540050101486294764567943083479421646624991034526252658487962349769410353442314774210885670846399155171340519842464028, + "P": 153127166581332438310520143516385326126483492567713235985197261629937813144159736532556155935542932400915415638894055561559039393206506715138655810500926433903318660850500965291533452588281294549868539917643904348505960828584736020662755251135406103504747865699084465420051482627617294913572225855958405149359, + "Q": 171189061442715678583847565447456642162416132715050131823749148594671007808298594218848203643743977657797196421218011164769987710368880273765425483133166766236779698600904616027627571296104848396445980104317933618484098249011977121220351835247320119313999534195781664790847774265358971620807603173668543640867 + }, + "NTildei": 27379961403744167295912242225095237617638951801557547387051269257520457031210413715939931790754973266466537870803816292314424280065496506709454503499442183261206231256170689796298328852681013257582491397765741608765573139753333535953972804612422245235409953765777197598841942060027589999774070828591363752211922134820385573566150886987517408090647696990073224331213767686182562971993794334003151176153009418575611368909716570570907093953842416814441768606369950299739392058260323312595145184449077054010467122738864844456276765148876274670907660057159426982565465331773172012343524531877482894579153699516444083063057, + "H1i": 16626965275890433529811759056049869939902849459257039107638638439909353307412794212668021825154083483636235553987427956134762634190488421103487065251830795801596913615064842332290920487223756278138422212871130203258620082436716405484588968008884706230186188198378497108637665621500812391126234472902356159614619960458813295871468684884755425931001905190222323710591482891532158363724902828577554316877826421261736064145190090239115547912908544859375725723544643897241148512902573283938821258936041652205186556623769523455307612323653347665615023770648611898212169671662622151668941992106310100847347131949729584914246, + "H2i": 8906084282415161697323497430017092450283671015563013565917297081844948550443092434132187420562870573529295453968141573970683757283950135132283045411377248807946736537398366381274038553650862493675683293949666283346447493159358349561410181410523475328218273839488708246837795825481208868686976332601244741380841424120567072122918708660978238016050832208589868791839029399178687496418374059841203000601566915392178906092662744888820986284758028119231080490447352125902596021182756026464181058219240660669142219896695655817723160504347202269699949479131109556579401035503671907859794104737249921099247350937066164223477, + "Alpha": 19362142301652692905581336423541877360572238544310455635585425110789588574018643592691027576467237357698982397642419031145395632071361657472511930748757255447268552564444341982307234168240267738026985827060311972677227231722105713227865893975116969677127685397487138638490927588186246221634743049352385113448841228486875261155852978271222544572545984855939762812683584380250742654582079815603183873785646395667946855509976657070660898988926558821916798600041993164180651583835742382073720358326364678372645994305211601432338835028287757710540951983762440041510421397737961744355367967738759693780887766385436867842096, + "Beta": 6362857398393859223889614928799144323541484658811219822494676335656223075972319990613532478253201626387985755175912872470112258069036556690243303564051004420397929492998047026288572652081699407198608397230736923390965402480297797265839400830409573710780313177253370295775104845493325474875320542957364482576400912882705653843622660078780463847936502890732196042958262948280758803235696625703185336312299201291520302369154249951121642979434553255243236571678600873578004152959257237775548373329041053335692039795003473584723752877164211259738037618359184771814990886038632785240546469466455747709077866088303692664987, + "P": 86827196060787703177766811228861952522649327977214560512322973685588118756387223893165421214432651692724411642117876481663642621142033268156549356736958168313729740706672393069877918715005385682615224836059548130401068153342542358170067929423289586010272053119614727099318025816463430149675568278827111970439, + "Q": 78834635476928972835643074784106746741740760909579612674285506203242804577798653784106589670858156207329885493261099734066676886838103236394735989736408641853305400315457060858037352320256769282827246524978408674841976955289538451332175125873002386523645590765260408353736136094749838547936815604719783850991 + }, + { + "PaillierSK": { + "N": 25830909043964384258374472442727155134029629162535675461622123755779908658153652556734553994813755341435930523081631106521478315853130541302272236764630740442704247177126473468530750864571076495627175486081090129958470195323104902621699582736660149158085909849993667711063858024340962659553640603132631783889658303944792530621195084725549309412680171792553429922236226352769304706463725537826023703793703918019805456724046507601809755834714693420556439768207084763168108781468894059039512812491093633449112544056607185220879140564783062709642971221746142490492863568973315333571590992312313739255361359759396249538357, + "LambdaN": 12915454521982192129187236221363577567014814581267837730811061877889954329076826278367276997406877670717965261540815553260739157926565270651136118382315370221352123588563236734265375432285538247813587743040545064979235097661552451310849791368330074579042954924996833855531929012170481329776820301566315891944667805815281148304211919727284712267292031459079643070389500510076838544552501960721547603995064900360713638678824811232914434128133886975027711975862860896486577581334885276658879937364960329435122406157642345418711766248392689317885698535778773982456050622940902001076670027161106834364233573965528333319958, + "PhiN": 25830909043964384258374472442727155134029629162535675461622123755779908658153652556734553994813755341435930523081631106521478315853130541302272236764630740442704247177126473468530750864571076495627175486081090129958470195323104902621699582736660149158085909849993667711063858024340962659553640603132631783889335611630562296608423839454569424534584062918159286140779001020153677089105003921443095207990129800721427277357649622465828868256267773950055423951725721792973155162669770553317759874729920658870244812315284690837423532496785378635771397071557547964912101245881804002153340054322213668728467147931056666639916, + "P": 175547332131700596332643985411953445364285396793922236397152531580104855525666309014330963176468101037134760445009584379299945261166882761478986136659800393298707163157728888421063097696086212550575996915466014568022145609757912936404396290800087234688478752402915149973028638026687405021018235087872545721243, + "Q": 147144982098533416438601285567931432731823477600221545060072801035522761833055307368597532627106016261243418921387300756680942317280036709022029679821562576896246455641394617300689840065086762028291734825856479815433462458239771137467177859388507290892283570688596181445222299963412665505875976740467037177199 + }, + "NTildei": 25927852965566581567847583625399477554523810258529336226969267129620173802956991771598270359464569659720196782169590231503225186269503038179712440562368263745290567251484099508531714812334071768270634145698532798140913504582026582280062026377559466432145263167098712316151340044267651404932505548802605445652408337762295355533840414032330239681364603235135737742222937840716431935223017794550268332318031326298224071166014739058780985359409100770780366455409387736511753499262480921867134321418868356130145185757245097362914104940130381998055734847678903943371725446192349148145538700413417918013758433169686184580741, + "H1i": 15804523353135876800475834349545491762542778230982997814519967115854573587892273606606486737801971014062097055388318296506681468080265720750356187031802356097241870617783982744432160922800283091417881769569860714241279131023688824239530238554997760699150956390123641040018612438369973066736919498014236134297670733858689257533276493187529901993391466423600024070294080196614852386557852370082689300392121503353941221545646029701885343993689194702351533944759744724518348719587101542837988635475923444269032183968111646528649240259201471919574068772947717932371207319889028578670276027150358746159646749728244297522136, + "H2i": 11025329598468365524175262704737607247325213682386502653278505417689391672261132993450693023621559276315684910512180340057935351122618224938775800916738509269622785441636788277562666890499819662915962482284816564546044985934321345329348547104018934498887276424361172470159198193542646359352675253198973267682821784285274373388060455556474725845458140198866388265987582444955048505999594679133935006354809371204895049813910311891254910596777362465048314819575013133814166052451505347954373436752810836825044354575074106354096697001260563209980794048529049406660305808048823495589725911405995518536102269179999676180152, + "Alpha": 3557532144045049170195672688302369964433428746392919754395112964523048777617953657220760780538423782271976899309766439298608725243959078086794455828978916806024315336573614553737180675361515473940613333454016338984672520405473037930759516997425942379619779206279815318094386347617421243540736120035213874655475175596105431420677619744425062027372427841140047204566784477970184836921393019836936127757306322642157485738610255958082276200067672673526520895718282493883004988977693602873907920635551522982903124092417988458355157338131538620341300023197953465753193313232948507327875381631361325380240061579764902703294, + "Beta": 5002241585952709666217520566575102327888547287215359854276250959820482003800389794724621181492737245805405569786397540524221375376908392648503426879977481874610197451899304829364904223400308606906248693014769679016503415660207820729531451101242391418579699000963533605972011883330214409543795161925000960123905760362635192722310442456381292778067230578424832829563228336898601808199320885743274451150535944187557900414838506255110392590404716547087470988577758116229750697049126640019646280591577679418409910333263242523335395228302463805123271470600065510940604726977644349961029255585110448391991965095290634368239, + "P": 89332740299498718655963563832552296139573366359778135898214314648531204935828178034374657506120602093474597211532752889776777493722481014956220941797247666018862786041892148255049671649072869979549970411187527143078130033949601368083930942405040570739588821574080621058173042938029612493224745344469450384031, + "Q": 72559771699156286285356746558872093708436613117192001800425810368270187509699484728295568888016624079620077087141427421813836236856739956793849792312548317218935978835865309737081394883719499192148881220226823820473073109676277629940134600850661998068260604337107208545181181739086650717082222335821940273053 + }, + { + "PaillierSK": { + "N": 23065912498625363368784418170138341778826946434482115451319531776152242927251863276552420115757503337592758574390309515048711782597224042154721218095067334825599550618015365179867223948818339233249952917156805870122840463381706668679064240666007277296654627200222579128665223752794520653512708450199286865986071009288476462043006973277988222014837561149352032730672220394411196258353206847937373212547323842118258709342460170722253484057285457163985719256092911572458679082323970717387764280637855658903845136325968590782831463386794968958387973532847000307460025371001975649460405401496810667270775429943042292382153, + "LambdaN": 11532956249312681684392209085069170889413473217241057725659765888076121463625931638276210057878751668796379287195154757524355891298612021077360609047533667412799775309007682589933611974409169616624976458578402935061420231690853334339532120333003638648327313600111289564332611876397260326756354225099643432992883476876642127334833657305861517249280378117681052754567307294587673307446358814265874713365417882272769941624334919030873172295555977612711241258176905177705369951366800512274013685977079130009823165361594855060453545505944475212512057372224875585814844262486470331817627898128521743969602188578199448108234, + "PhiN": 23065912498625363368784418170138341778826946434482115451319531776152242927251863276552420115757503337592758574390309515048711782597224042154721218095067334825599550618015365179867223948818339233249952917156805870122840463381706668679064240666007277296654627200222579128665223752794520653512708450199286865985766953753284254669667314611723034498560756235362105509134614589175346614892717628531749426730835764545539883248669838061746344591111955225422482516353810355410739902733601024548027371954158260019646330723189710120907091011888950425024114744449751171629688524972940663635255796257043487939204377156398896216468, + "P": 145206505130141043745569711910205826363961151745553547786026399755900805490941129590997457812236915916833678907669888898626000417234582131123919324041778858794517905287738137556843409002835746265171983281404732144968652497797341715527783703788048505203219267650381902860783337984712237661821621754560143574207, + "Q": 158849030062066329594088954354981689912843762244373673751579405479948837969548089814626328004251161655885147186120443761881139048938919807439317415697322358253421274302631555282893499680861652619026822321374148516955719877108676817836075084609200630627117578378653082964366267255054941669749431032083252591479 + }, + "NTildei": 23353451403880499638101740929964993317434840359259352386277101729520289989822590334961455699104821366961299902213597254079779783615424581373386904716746339412396054481760449249852936074869562958240053640066215910717406723131269261806579317387954282397289066249422902157380333212438848039641276165676172326960704513890533193668337095980657188250419993445153477277891847000595907321059302104023857014870624252509928117216258082572531311416230778037188047453621163960521775657648034223864638114392425244170761168192178325842127782055425523123854135192111759729339337216738183397069843572807322741894990493306486444522557, + "H1i": 13346824370400119119869025783756508602554700938327772269533359845846156419250361724793307558310805254829539398247025302437265526989842520342609203007009776212372850128053543206244441210388906585840644675070196146298804859467907152880797456961909323960972976449383929475978615742990155343306150115613607913448440607791628316007854534184481947646215509957450184686433872692396297220727520995333811927197936470912284016018460822902146743527015536598977986242231111609054533803264628732117169472967743164897141170622447131174280474761759891475578895655790118691513556635067197531816497464123133741313752010598546907012244, + "H2i": 15018166569778090235263484123947046494757357564656366310054592788317263401298594046095931598107346648190306996355581281595417026833571915270893607610243344316340231809255808361825681652746200432583012086332428775824694014996961509848261586723901467731575983751097148360501439720865540838261741844323260885910091672899443494324358314145389535315744930578826750100186736982804552101564302773218019238226240813779237783181291080600371656285410141670086815083541406379617049541407091966929575272319251074959420146596716918461389623225255886372435675191370065772841420920233053572811381648395108599128524647731056585588671, + "Alpha": 17633755622675888000221033724237197630133716600149748330660531686696473309070391458826663610116668841779459508016233146818372427704957780418995855952863915010837534885598245583731226556406829370901243938610996616309625992867391023511128919222814759527534069352447624455705179225379868550179275522414232005489480830973879513424270089967544693512069953686883427990802969942552333504791423227418997340839909910255900981003278864323430151167874753647487100290884039974836618543532086674331099143133079644696557763013403100085125190519923269867253051214407736759016072563688446653173492353270253978874341469904557591823130, + "Beta": 135489918914187386623752132466977672845085721279427965155184918986537685337367008480250714180328848265129006028147346164083153986529702697649472831205356630626299575022545660331157314490039896182556416110810823877301030065479847688367398836374031817793029657001388902356613574141436271114432658477931948551672773956311438674708581806722760784716088688910830181854814534617185219675071421860643496939108873969390301357158491496901392817372959381332465530987575185160667817943781369362163603735567363694703326348130861214906612390234150068056207731488607347103592216353411560567608944468556325341503932719467323578307, + "P": 78108266215443603792796687456594460425943062611910425499679762716684392183095593487699350311927576866886413115023746697130128270711047006006018748232515676541636830129694260919618760249886025647045393965615249245369313081725993284581979630692934347035635099755825120784706190580363532110043862172181948021931, + "Q": 74747054746630146187267388949903892214579999339143774290424815744665666110372195436872626075117773822145830339286363617975536826059736738503848363888387233148745743980349474599108916534491768176879594827839882309631094664169380683016974369333652432510913782481537556047237741478782413999367848391175404665669 + }, + { + "PaillierSK": { + "N": 22606356688429172951402834943047148706681707438307154181872479362661390966910372081065055234509629709347440551663201410375128902713010513207421719067083956779722194504828190765598854317110955335372129732360219937162501410160322228701948487696323490746588479681739955524182022974929069786960452314454436300032899615497054658629125342237672800419583493569372335018384244598397217954811155206265579579894898328449381470397964301100321626728624538568526186173071609179168174164259298042758835186998614673586764053792895986387973923981038873264966275289012488606801035480191814526817970869243761921090389132316652414654809, + "LambdaN": 11303178344214586475701417471523574353340853719153577090936239681330695483455186040532527617254814854673720275831600705187564451356505256603710859533541978389861097252414095382799427158555477667686064866180109968581250705080161114350974243848161745373294239840869977762091011487464534893480226157227218150016299312090781459959557667330141569900635244083477430558345531993936865889996718219819327155109696317551074158395671913158179910835539673348647805342808794945729312363546167708989226596929722098225103478706855509271534122535589640177558547253229033687213749045577023669914979645915189351289530682569530101567858, + "PhiN": 22606356688429172951402834943047148706681707438307154181872479362661390966910372081065055234509629709347440551663201410375128902713010513207421719067083956779722194504828190765598854317110955335372129732360219937162501410160322228701948487696323490746588479681739955524182022974929069786960452314454436300032598624181562919919115334660283139801270488166954861116691063987873731779993436439638654310219392635102148316791343826316359821671079346697295610685617589891458624727092335417978453193859444196450206957413711018543068245071179280355117094506458067374427498091154047339829959291830378702579061365139060203135716, + "P": 143969838875208459914424148959304744690953282434224761631629992198928651712793595639569459453861401362941460483819067373683364327397199217171568947789811462392064610509096254004612299863127786419119412357852767331632125644047223568929560901362931724655215581213925186559688582310613525608018395596527210141027, + "Q": 157021476616530250095583428430355873622052119983249140061550618324557523104925170987355810221644291984291693122801407410278440730147992654059006539664207825317484826657866370775769693276042690717437684021332200513273553265812369340919619881191489507718321807823842000428322995102769692903309371581065001378067 + }, + "NTildei": 30470542001059311358544864581700964312452286815547431850428048398402842728540440455199013303014044028998869074106224180597437280749216708451843985285371329063323499570461553904499171482315318438695844513028326200137011051331637341052828006382974574239930417250086992073114345872915956311477929050392742709104038398139457631586268586206994972782270146778605010758050671817865724059055242462751549813548726924547883117888839229533774298607207179507286434891366499419207005677509084366747961633160187861191837135473883737818174390106905316579599470509053184176944011650865951709154983398510105001905623674273817393073409, + "H1i": 21920377456174296746942772243820060533336225642375477937396609340192189441302481420024901437091063306794885485267115128454856698543006477374277457721792117252060048523206361611624078539899283928328719507253785715834321938294926175719016382404330639863175897134271005823318095763344342049054316893723833313780547942147123639712524569636899435970442857758418190751168235897714741187978976954239482419284904866220995273837977878051138406566455476400483032025081851591260870732090817411044645609290508792564266381744678057223166976677390423243300709202311499468521340268480650697451464293207233723659475080890816281139885, + "H2i": 27320902983664162265003874074839421255536093861748050730021231655841895136921344475303774915811548220930067773637762091951862403572120792007420397959502540317802087627271891716968148513878360778068885522106079022473791608143561407264806882118609246000965031034328709312188850366681149834280433935100113451594507183933365173267328149904761128221946579844295521969241069426976955823703097595358780982129518814579108035285241894075750809341395247997610355882061099450897218804460132685552566591309446894810583223472117165032650319816766682069960106339326705210939102930196367215432651504151760114378568285353809654772240, + "Alpha": 15379133801450552699341960065088938208835059422464506850595596859181661925505742069844983690835920379973104815047557337190053720119039213532772924816520545512993759091766363488793725869325215798871949403295425679337273198187146597111512105376022499166836524603715983943452947695869572066285150177107752287420660823107234307539437626709219392118774121441685021149155625487935916578272245195454553610288482723856614683626632797890250032324669722941060879698741843554617721026626451704061241730271849324845862394666439953102647179454085538335878562032392460889214501497031133340602887986661832430090471199478848852793115, + "Beta": 5994492990504295797673478586068760289745106381174782488960348984944700609322533245022489335068218703300204714606826655335406455039013591080136707058393594701991934482642925967630572904949701979904564986623805259765420063144097817203746908685253922269360716267688202293669971331128210557569481447501530706860445747345504007329377783178064641361124116428276616101547203299259462142950369699753065894126900098718527164951665312141896568179134170650906245501503509762078451171028991063659724279048299542916503707638849857947969178626137279173974553776844539461458005858238271552448433053676834989629267454021212520221375, + "P": 85643937153092517214730368225459026780186476239789908423926779578202171035296077356023371800591712838058751759866176672015587492581336762659064576908587420562332478385465212121386209083937917218747177703158045951743314513206996388395301390633569641359350684286536349957947372072491856659071033812316991021781, + "Q": 88945414625765632654998809263255816184072997245375012088994894048181582396766145724296399519584710047473792616810021549967496430113897248152826753893368652530317852232069428501696882410792690201215787479203803488156443976796791311566375947754087336390687376530681554216428265022255709896788812038323802462721 + }, + { + "PaillierSK": { + "N": 27047625628233403022776292783720594195678252715446128599663136523845532462424429207096615718533815074170053211782541707826170493514677870773938937634454126404201741547311834277844043098367773629579580033174700819898159106191401908059996330490494020229459700869321445288797242864565008832251159514824911731947972611278237390474044333041111749935786536646974739230901666174292064992179737473992156216514768089986532818441072244897913507496017162461843020042911344742361184738938150712029645955041247500880111578578308269496706389623420861856438506737291630197981682248463643299983141660021660655012855013626865376968653, + "LambdaN": 13523812814116701511388146391860297097839126357723064299831568261922766231212214603548307859266907537085026605891270853913085246757338935386969468817227063202100870773655917138922021549183886814789790016587350409949079553095700954029998165245247010114729850434660722644398621432282504416125579757412455865973821736619883946406224043765748563689649054735702285037858519322013205203578582003854149515375302245006488041725191389532076676556000022031002833514585325868518809706246886286263166640047087041509591814466384175438834611185168745574353123714613905157255753397612964432649351626761453645419229538602076033046494, + "PhiN": 27047625628233403022776292783720594195678252715446128599663136523845532462424429207096615718533815074170053211782541707826170493514677870773938937634454126404201741547311834277844043098367773629579580033174700819898159106191401908059996330490494020229459700869321445288797242864565008832251159514824911731947643473239767892812448087531497127379298109471404570075717038644026410407157164007708299030750604490012976083450382779064153353112000044062005667029170651737037619412493772572526333280094174083019183628932768350877669222370337491148706247429227810314511506795225928865298703253522907290838459077204152066092988, + "P": 158624571097728235677753723851158840219600988047748914491969395843535797203368449321572791696541162983345796079649185873260066595493124339127921788620088879627297318558408611011681246226876313733063729835578585710660142123702938927280881942340321924336503520773311416740213485696634135291590587855785469674727, + "Q": 170513467371769425918491785763463716268826187522420240692658134422118787819205016962284394067622436990210938911040279960500087788523994060709431225120604125696268007885969528491631428720197104127864219809961332908377025129380431780451377365723497959133671932464403017944224920802119228882805348566927841200939 + }, + "NTildei": 20865245790559151430973000966830401521925796433072469375851656842781765984797559456121221346381902366192755770395648833535459267083250738332486451616768404161454429808504087960302301727209457507522493522509501037767256183182737950844141194431714994067051594036539100376354890160414247723977821668436750774623220660052613442929198046177216735097654379398587066435969287387056672722332328825910986182213743757672588520770990353096722964594458174960429601968515320371244116711340468795030783075217738578928278237932844553248720136726741222703076819772949138693994998825683858017731739214777949396836586920395845955053249, + "H1i": 3428750533975172854086887376772229830275301990289024634214890657157400946874148043464447185889487831704579060503970719163583283904358983641465634669994536043645227683297520157066153104878836762595177298616082994143791340062139014838273198261670166670694588826455987964745962283338677180151652939761613731002793397185066604814081793874777006731978394797471500951291599112332260753331312075606135220623304702636996031015500793299896574861584595605284119815103214469563753920435088960491763919182917861416439916830973577794476255216215146524971030136608358485819437936236699252939899320896803061229508083573248385215575, + "H2i": 7915296610468666163043449932722017525347955723561129251519428104164017586681248400068640566504739562661354444718865258372230799250636823012526506870647105465348451839805557169802865987861942089489037897454127916980764839923481645286551451380784097044259682774019460723792000661926240670754023683663750185896374902940852625547822227777583364176405037861149432701341856202766113701134793765847481331787276918603489909729887149433653559422017386951214047660851604355765845661853893074281143459255727975263988169424044139424690929344475371816114815730063701996828475269503230900747724586767875529486314866460979503420598, + "Alpha": 10849318463569810225379982316338460289303118706839938431726466200230686136543469596201856766839870048292495183483824326476550161311155130055172881943396969956135186969155031257325219768741422613127134113456526898989453443225350825565578373868238991195852307804866733343591570476984765850376048174465384392420677383894639583346350937798176696451693546864745182757107269639712426898779877639073571746288439025730481721135377000152465885241835670432616318664816036239803597091345841277211591437777843405973766005660377187320963296377986476854814809380064207764170325238899373005584568967626966104335787399345949518778583, + "Beta": 1877217056345900013641521178786390358898668762660573059843280280675608895005311229257487934761571724012435501479185511665632221399024343982331878278400827132531435406312101491381329866142745882928918015483167089654879468194029967669856141053310511165347117902738197190224457443771589298625348043384417579358342914174847842515264115813497172161810170287247837045580481396272725366855461881498739989030088423116075327716420879957070115721657922237179628949648643576488605939257777639192108547146223384010453876254043525351148466588737906549348915465558989110214355834316827483833174187210485917243317079682539199157567, + "P": 74045233530739261202655115568073521208666388513498340257082191481174449006719441000945757747454804978788800612900443596941383920601831417279752561311933071817821389697472154077295976718505695790703796288082489821871091456396584809080814623178136779164621248223165319513062426090660180994079159899821715003071, + "Q": 70447633141359189062482826779230870072202880203367932960756921640396535327314233378688089280106079356458776203011690070420800961250548821358100972847771397115186223822876197010178438637715223430065983663067803371647882787157217103281145187337206069748192800331285066136370020353088252112914029905866017211871 + }, + { + "PaillierSK": { + "N": 27713370834080243485836599460751224751253078147815715030684466203607535610809093442156923387960051918128639269383977461254232157620537746435035622903013931401730164562307641344075404954653457708552962479948314585838669398135910811865781025080587885899335724638237023343114180657336000584640592121496149942226349867971156445204192020181422383616785688351042141710075326593290292878174529339531564877472677700897851824511967787874022417738539318554915142702912231616549814998553512260898602171881098507949240494976477817683583314212952576632120447842683656276548458112722488829971334500394824402333880725173181489915081, + "LambdaN": 13856685417040121742918299730375612375626539073907857515342233101803767805404546721078461693980025959064319634691988730627116078810268873217517811451506965700865082281153820672037702477326728854276481239974157292919334699067955405932890512540293942949667862319118511671557090328668000292320296060748074971113007974662539335233889472481957189379546625069059224815036625068431404397961920643080062562514178780931365202308329723062493212551008272919912567873409163838099808944625163757962688212466229543525816337442299089313132339785392340264748662100265526168896952436353870643738872346697383312909246679839846144737482, + "PhiN": 27713370834080243485836599460751224751253078147815715030684466203607535610809093442156923387960051918128639269383977461254232157620537746435035622903013931401730164562307641344075404954653457708552962479948314585838669398135910811865781025080587885899335724638237023343114180657336000584640592121496149942226015949325078670467778944963914378759093250138118449630073250136862808795923841286160125125028357561862730404616659446124986425102016545839825135746818327676199617889250327515925376424932459087051632674884598178626264679570784680529497324200531052337793904872707741287477744693394766625818493359679692289474964, + "P": 154229644507074286568456865191521442337979636658781418499533403665134151425612369121845895860068823930269224527695955672465183273123763082294559041527214376661171898175372174040655778585229739576787417453310313242640853207882512954513577517674544383611342885557759646035889186954092890498582767760002850819839, + "Q": 179689001570700449844618352316483415354458576264910661502543052762349930825075684249593856584251315104852195367612386076570809363399009632795447914566689563689025211127812570932569968363409681320820402638569325814677781434285383148109546124478059555143210354456987896457700620045964886016804597733486349620279 + }, + "NTildei": 23178467751283741082369676287646186324714832150274311487518867924495659986248305894686735348492167965058018020190615242749633280649444264949462951219063700136929807203294247835270217226523578022435366701980485471816238511414661936276050720763608885979205269506120055667305892228180245583280103628285071659347582006786258295374953961019527840845114828468478862865735195360344590793707031779744498576698952934657685300144780594195158017715586499283375564457882590251407632467573978814556618071121863433213315584370116048467067032102750826879501841645837388904200784988018610113446952558546169630426059608162641542967161, + "H1i": 6872927343802218091502336101315040778307521850864123659907772742428117707422219619842657326633062434751478627110125115903024530978445335054737975631895402327914098027590196038200908403588430233508767528595145798337888653339905702780379071159070653959606796878326285170591453178021836675773773896199878513113667938037877544601679608937144492045456567314524739980168397120485504198877612658398322060314139300200535845311284357115767939043034527885975243792431503002469732495618324343447322847704309003757378677377666543182575318033932347777038928518577152508667461165641799688761675384138707688303917792145972873773970, + "H2i": 23165848035094274863058836289708028390462708282552352657821011423856601055530473520962764036637474261911371787742641270401246095112853459580765286722955846661002572890938216694497829532666837770643686821673027944840738996720071357307562762511337466067143168389327988239844322748029161124457175730450832695279145412290104259924736583168290202984275379985727615917318375449043285863555379546340579918052717938628657004364475006243930551096338637508985420586642655890963405774697337031318619850590893433286070125656942871599772105174776408894665901944935190837734249454812764882278065140665500908552054863731345648364949, + "Alpha": 21786713408434347755950464282477174059608830820488667674551372366119411065411119302040027808830351963526672169664755157611679997284430757340873371943455800931608296139899148541359206858577289594934306528797686499426080978137076642681384446827616387481232809098505468598512693869324408122846144807737597463875021520443344343410506793234841085508283557844904146312522258259390399118678921039932071584627236757074517818977154643012579474914155382188296532321134577200237520612864625323621475292135557755540603859606401106324775622184399855610758794419588002519369031123181522275928435189744078942782790604939645453975398, + "Beta": 4104617482599685774457246289911952034164342150253904097208514436398991220729710746837700219014417485431329928575810492826269210189977928488700566210774045453327198911978137667660489039183125270786311301078972555560685840665544938442741899854343625329211143591267052356732611462951955784934890453356846231658007221072797243881272675464780473931701712665205448764812772493164920929800199140094105327827419740831077721073524443105697505567202460834636583999375154400898302817457508108606050800081479410855137159263919685840119477899789431574041640547865442796611148726205570586348379144166183776647352608167081755507350, + "P": 77950060032468343579185994919912537924812184818550559461582869410538670889154559681071056461968205131865281572183498311698324267238881551290420092266767484348359609352309867345676717765760026521014271427331257017201516010033878071203876625010394809950884693195664626684717586202892713811663139192002971483989, + "Q": 74337555806978441938524870993897958506476655509433780149425668656834394012950977946604795199139194270454252897684124101591342649227459762160159168541767298921869836282438244204485012717627483683884200743825731342936797190116828473116032031371458648583476131086281993266446715268278649104188316143532693355829 + }, + { + "PaillierSK": { + "N": 24957272833640359944606552306709201154941495202818855173148791526465944389676122670399386935922593477430983218199240081923962324651914992504434894760553616593003624600158476672927520235067763659089734114897712569632763885009993549314169194668556465199192686655847221917540491925121880095849055008766019244904440817241604654670838290056926273431496016849927431567317612948300129419428604263344082652422846674214115360923062830030083308803488401732168729988083653647427263760943145836849019619521154433337064908474947754307694560751627835372939140763267295727371026391268755152194277250567804579146516794875835929261817, + "LambdaN": 12478636416820179972303276153354600577470747601409427586574395763232972194838061335199693467961296738715491609099620040961981162325957496252217447380276808296501812300079238336463760117533881829544867057448856284816381942504996774657084597334278232599596343327923610958770245962560940047924527504383009622452062298324646542433799521966837917283365195342428130041122890330032363760021391249649445532440270870429682037915198086699784046123770585074874084736671762709760042333313386252279099354665831552698317827655667203231045918199211448012582062804045086408280336121103276477340988975896029662826122161848517979312698, + "PhiN": 24957272833640359944606552306709201154941495202818855173148791526465944389676122670399386935922593477430983218199240081923962324651914992504434894760553616593003624600158476672927520235067763659089734114897712569632763885009993549314169194668556465199192686655847221917540491925121880095849055008766019244904124596649293084867599043933675834566730390684856260082245780660064727520042782499298891064880541740859364075830396173399568092247541170149748169473343525419520084666626772504558198709331663105396635655311334406462091836398422896025164125608090172816560672242206552954681977951792059325652244323697035958625396, + "P": 164559553231576646989435271287770899177316664651787488000629474824994168847019037077943237188891797361051862944535918623606362883567820695367293957666625166723169291100862532485988735342519079214914506266997239959887110153622879189386996782120049355053316434418853530750445937617520924161979014579380348174159, + "Q": 151661039079993156249810851962667965588309500419383997071202813410407730538802726967248350353413135993699422148130738006908853672379410887053266557073503061184009803215510799804832174846972248725514746896616107885715614199582060158388018373057073555757037714643348666761853361158224329332293456599419622462263 + }, + "NTildei": 23830888077520881453233446503988611123749630535309813911690158182225486006405304122358483232326294201928186772561843822490134585435638159893485072504543260587312249629190743400691007576557162172490703457179947224745560882563607379215015331046307554792123656912195037890020765341761126673082675012053358471989270101504227929140569876357092633271803309932007324964377154658713450653633778572579221006554600794664420057899850086646771227143286932706774586467245197049500188959246084468874010357109872693757210139450775630837607245995002063722933357963726441341325062599726234611734698968922117337422752610022880456707497, + "H1i": 14235189201622891436120977458362127444873007548487023655825180277409664430273877832514278990753731755812955981229172184588331254931032806146534908352035731340033024828000168406167967165406710817679684914700958671441127878862280643750269587232414892051974080419185899999583146931679402098869281641530469773983235055884902763802375936608009426963605198729737721850017850154718301396685774021719654977192469892192838633720622491978073980147678648473339445949810420505764553697736397193402939114608542084086607945118903339696009864836172059160062035077752185580313723025308105287434403135251572010285878021317043703104717, + "H2i": 2268334288294646800145355294191026794484014279561150091832340684929246598596194541594709153919718386084237899928939775121256179297073050497666643405402560303007721972677684413404964905770942239002195669984940166835520554646992972161152779346601663585319091624984434724173364290242587194333370182418800364973769616557948159822898588632806999867725354182192286342783127933530985768510975884389249001518558553377984089949879775458842434121943335667415545316231559690036365439279165234702694192730506452775884867471134478699213343533559947809797510068869281921567665054311496428789374424544319441661567662587852289556636, + "Alpha": 9125170002207358039994180967407646100189186815638452427743157659966686658321515603539283891427156630477194039257512467371558207279086218816362353994232739372823202921143558975622653015538681736851604391985076340031121006376689427790602177745767586880984935121277428992531435360534053012589197348655873618502410995034473158185776359321628044411214807542407401305093777261189293844824383381969613127529823897150657979931254655004750992696666044130516086673616298173873272000297635790675715068071661523796174291185956215677320655725874957409097476057671013384016294243376607476998728694919957783392812784586898101609962, + "Beta": 3558285124063019757480563950006414721712103290204397880340008163150130022533299818270145515621347634050406430608742912592932940024221562583498825289350629962105845409872459480143423059508010772255695844085490869508854955246734967705718093246567161234424689492145835275789558368534778295490663486192988948192092340983339459488486371009974762630087451927927350826646176186415890210432176609850937375977298670239899639126829649459424977331765639762720613274046556973250366704139867924791317648239547225160432856122144606720136161987979484775219076057006877160861911617933379143555827406303161698562548462610726257135496, + "P": 78541377945822227965134753765044920665659042830122998517037235353690780385538242656818528297629828188587855624149558638300631699727495877587991647109144677876625317886817462203619158094774186226693591902177747304097114941547515942773335631295363405147531681430107086784483053898906218957574402499439722345961, + "Q": 75854564500890876483496500384409231901855133430864952677676421721580214262558250045833452600117995640028651480578316408566751206202130636971969321734249034279687547171790042892542679167026946573968535448039699119565503454817512047879316013647601437778895162289420329460536420861020720557051409157484742053769 + }, + { + "PaillierSK": { + "N": 26723870799992085108869546978153583903369706088168083742244159090735484100208146492121615286184432514205245421757050777132600249949760335204760440730426160499364110451759957490921645520416721530671311214599458837511388928097547178394601502526807946677793504886911880098281711166642344716425177840605403468027738669850438692375217909468158239813685976612027547845797546922879586543279806133533414016574796969254441081617638273385383896185880814653525907620162194945920224483563467627618890567067194348363928270334512550200498125057498503783857569650615091082302587171567195208060686741397242999151175419270358765662217, + "LambdaN": 13361935399996042554434773489076791951684853044084041871122079545367742050104073246060807643092216257102622710878525388566300124974880167602380220365213080249682055225879978745460822760208360765335655607299729418755694464048773589197300751263403973338896752443455940049140855583321172358212588920302701734013705474553708807150136226955375830741784632529113506702654232057724314933072084413448458350009716279537919279769232319855570869167817895891596129867792773486264091695835351635080989996098592438174094441850340120097267749483028011115694256775616330066545522210354352199451257161339503905057976527678038557352098, + "PhiN": 26723870799992085108869546978153583903369706088168083742244159090735484100208146492121615286184432514205245421757050777132600249949760335204760440730426160499364110451759957490921645520416721530671311214599458837511388928097547178394601502526807946677793504886911880098281711166642344716425177840605403468027410949107417614300272453910751661483569265058227013405308464115448629866144168826896916700019432559075838559538464639711141738335635791783192259735585546972528183391670703270161979992197184876348188883700680240194535498966056022231388513551232660133091044420708704398902514322679007810115953055356077114704196, + "P": 175100947633664948331242692945251377313511570661714439919748314241963328778125126076966805024435307337357532579683501364813737746463784902767773779423750641597386390008653689590901379678925761747720342351110129988568100780015819990211184970470055575667761657889758786820491815367565513564626268882784901142363, + "Q": 152619795387413126614212864461326952803199983138820000569334493188993348357512180559530511530929102841244989499490132309428420103781237967565874105152897331794654701884110667866009195191083710268019044282722180017394525311426661562257871128912375373543781092968732022337680603350669675470596095031496749815659 + }, + "NTildei": 28624624686932925957150681042929273756809396218326966135018950205838122251463678085402315398088261514258856369014648390578521215309078104097698418324220723299847605507652052055911798238666904997894656234380282614314618649665242142143552491273511194294759533043630690352614458759187755219413112817424308342962950527695017372689367751993696671537428244670316113927800794610524703450820767269914203908662968962804978361864311083065787611295194701569030867188282226742716054326634008224697413720522051224244583013312474610776871930848283804012981928346198764711995247404132952144926252993418758071365354926653002833164209, + "H1i": 14026530141610668143856820420407656458432764374680020340571355631267210064006968072799105476032725089332039260073849275232014656789736661391193504152100732745094483418964125973918903900336895808960186954958138038426859748265459715997561763338475911201695863946142914553100703987724399497173060195922367447476997829115857087178783879201403579924033786649966962715477478264141714261448279095640953046222441971357858519897068717161539179362097372991276894926858571668032687275950623711928425165272738042543648866916378553081373750092641340783454021964459927757376327530918382782737461814621557767837977603932385255335438, + "H2i": 19283799849145394129320625350432713426475520862461400544155708240711309285561900932614928510337804121412965541890849867199640968887504032199042841733812607614755196200526682565756047755562312740623800760856499926583273826179391304381102328756953959130136385902351066167547535192380497694912835168622129179025476563060557206669766472640525587783151341927408624850912254165146029128771342027356650114359875501951630394635187190203263624041937663862426088837501407972579151686169107300498907506758915191333955480218680703336594433601740584371334487880159857068388403068198491336659162154463620222655416430696186215208178, + "Alpha": 5749843232223250574850558859986300041942204669388550286914769306149925653176196026966378499575714834222249624589331601858347797630909562813946721630811370402107387056922488419175647162616595418741646966864878906471955454249886174549430589585293438801360784160237347119540713862706724295853522854421579522800213721297410639723831508165742795445446556797408522127106494886716485331369696390778359617445809582186515978139306075539060603968273888878373614402427413436785066126420107550592965029648130662941620454409579881014399966348172506501799820496989990227126729160499430069315918989279002409454093802288365491119166, + "Beta": 6753796314668828023626742400192339961053247805158968448791189278405219197009230669389398530419912244722385870020796555412561987878937184217488142664309567853974200613130037797655518344070788332814595862356099067820866002844120560074558472034802025771882721224256726289456093794408406800753595989915246900363486470732898874260680872010366555517719317138304938242645614190384845050878484987925715606630250172662533272249966249432135841143176301888260172433813397261471898576338720490590315697735970189528646803089703806905174325157005520878377291785478721769671160590785110558563084563103554994265281629148478652360626, + "P": 88614852581497878151639851927541736529406344746355807023626732085240385765260309797888389804578884041830053182988789251980628438677388015503251231638214169890754770188429030291098618190712362073204249318855083659015028991496118650155743033232324736954298607449121278761444607904349233916727451883796343236401, + "Q": 80755719422450223090410337056249297573741310324854412676580299097971970609746616415696786961074202704926836995119764697750125109322932545719762755190777768760956378432466025018305400229445267545918499391237141624421234190789960881879608108546903728672110028397881465289820535627855539819569714072120573944301 + }, + { + "PaillierSK": { + "N": 26031871908125071401598913810935075639993122314702909223352387013254756850476217922269138225633646118710113525677829829960378250317168364628938674751357403423389801750904028738122150174417786786246791232420614321411287181275287316177615899664334577860429869495881683427458389699589380827444427594814760879588414915824416225999375189611722231623865011980429668268364999466051413587719374104686006165191148064512549746011863839563053925004413360911815280620599852256762900911150000345632275417193223651302865827070489670111089365401438823599873499095829996921942409718398923898306482789794736215298857716549836555989913, + "LambdaN": 13015935954062535700799456905467537819996561157351454611676193506627378425238108961134569112816823059355056762838914914980189125158584182314469337375678701711694900875452014369061075087208893393123395616210307160705643590637643658088807949832167288930214934747940841713729194849794690413722213797407380439794045566502867203995004037539785914716058756293820978784482496963546603747400145538434837572478591702286896298848557523071670800129060594094577831459038977033630391408442182918645302825164830685671226533422534755569497336621242657758730740671528514851479288464054379855616380445539909503270816671597988590989594, + "PhiN": 26031871908125071401598913810935075639993122314702909223352387013254756850476217922269138225633646118710113525677829829960378250317168364628938674751357403423389801750904028738122150174417786786246791232420614321411287181275287316177615899664334577860429869495881683427458389699589380827444427594814760879588091133005734407990008075079571829432117512587641957568964993927093207494800291076869675144957183404573792597697115046143341600258121188189155662918077954067260782816884365837290605650329661371342453066845069511138994673242485315517461481343057029702958576928108759711232760891079819006541633343195977181979188, + "P": 175193909491658409303441593996772331535333119087776217371039869663916579317191254110238201727602714098220221701404960629378784339440152844135984492488779188766893745308871440662125490556181782723481189132778325273472869310884471447660840732359915671523955590789822708843147906114127155048867316390174958534047, + "Q": 148588909190159600063672938153629860212166273699934482028965669294289513601891773706092818506361945840536926613343832790333540406852019878523633210033119000735224348956763067679544276307380497236931571092641833698621822848069036634751177020413051547459877199500341478230573992600790053708357056963684415476679 + }, + "NTildei": 29222158298155166695104931116299663569618664340728181773291467527591647292530273599837988427680089318168606469472880438852377560501028149937247580344563410102431529259509092211760857594934518812570949359176291554878925494195884545556694087575141351315368061600345950624347203205726805958587765395254840485607078449641835964821911353876567995038822236826436962271966340946461634035458740774858773419413455827530914858630717042374682817672046888540678530127753422371452644205088652330886737883942897332269542410300063340399452234374194502581172625744279585001277931557331804530241670315030238599435963356201072962156397, + "H1i": 330156415982565933027835973031402729449144812191428443161662192775434549908320527653614414300406041910737508644580222037134018847562136441606694057055661181109818079979311818774462193567531548078145955370090126229467798369284932781829152514373818985604751985752868313338748537039054113649045949619130272325727395658223111618681077583366422166733895629316440353631626308960917331548141842027074422722329247143664566090979920518467678017367651549718642006589732631357480488434477693504802314822108194348702444274293021973608504804124921430548183510385020028268768762905729647397798926600373975723792889415740814815047, + "H2i": 27407765995132388244657245696058842846465193613457489284080482268486686104561134939801003931949032949349693182031391996333954213993218373542518382621254706107358653562210674932655912397308223379879112209727096882491911718896134149782331390925516614741126388861654988741672110934335383394496013728482141458602740141407647241643946788202856437366438560178498493114705142609086805067510627447487746258780905892696786452619355102147293953940712069430051018401154466121711835154545618945252550009441593572452925091473697461656259197131183592837826794983800860380045031251238135934530497833914618842990437859869257192176021, + "Alpha": 8068703561045319338791816950135168271972282970417266114695781856026881349554751073620653609035741856668532877061780357941744224758942321018927524612511142941437615836787051500525059577663406161360691241043336128354340487680383425224760004367593022146314483044911756070499138562614483091857328371555422197670154469834386533594930297354597266368770821905394957405974363652387811953709857735678340195202334066915533464282746273474089083488517056425887755155850273112055767791569124454947800493677986970774563730647378380838204251433756155671722124661603753349169027630588573814795388735180612903167736882665792282027290, + "Beta": 3876473524223166595531434262908652981848550689117549535352822730295873527234419005367441280370944018085254857857146880132845179840751534603865359131569480133206417603294180461089111640881598712416328401239754643080501362221175499928930456768827702486447657750769588136740980575221130311286023262994112472080013178032408734731204598247998816398153141077192215917271963983206580216931080496594172278907156103339941014926261799513693004154717901423488370204686970158515566962370124789257214738112232819848340411307884191508950466727915323399234486824106365600930575170269338604677602056045649311053946128454963516166295, + "P": 85938832369741157120248968985971252483197739348285427991312924646208959859247514072241823171674958588421856970294017064555055021658433369678725136794927514249178278577091017403091399071011587837077616424408208774119082431130707434446365575784617895405575087152686547951651267594622353882191307793278148417669, + "Q": 85008597081091521279279601152117768515348019100337500136270928443094263907602241674324161888026609784810244767584333071909152596505153345404962613015958016969817584862506612063866664619252142344848813396485808466529767920065501945500364065938090706906012499635977077348093727117606776179328595281841063836211 + }, + { + "PaillierSK": { + "N": 26661616974222403359414724893859447643756557363346107145486809731184335627451501798120080086145787176627241224918066258044217471711997343867221990736146313313811314986971880028213031329891734757490529177891431337993307452684715254637027899818137617298154454328457812867646831974889744384042853838798700705793154070216628668751125286673961493037131949739024938908734089906357464861596821906243728729043875921287933895702418824027327331512497782181841843772668327150392233584918678025672404993278685654111687621551222648497781202031677301491040407149094472663523938181775045485674768873433005036746455424340767681133229, + "LambdaN": 13330808487111201679707362446929723821878278681673053572743404865592167813725750899060040043072893588313620612459033129022108735855998671933610995368073156656905657493485940014106515664945867378745264588945715668996653726342357627318513949909068808649077227164228906433823415987444872192021426919399350352896413334249723881600151417035375336671411497492483959164846859972859601443532060856725699957266443131509670167166226041809296996872390306503454927780645704632050736339055782287442955961439332302845153091459535115182876960631053492122048218683041784467611006347589134242358214621901048098413591515192423898257438, + "PhiN": 26661616974222403359414724893859447643756557363346107145486809731184335627451501798120080086145787176627241224918066258044217471711997343867221990736146313313811314986971880028213031329891734757490529177891431337993307452684715254637027899818137617298154454328457812867646831974889744384042853838798700705792826668499447763200302834070750673342822994984967918329693719945719202887064121713451399914532886263019340334332452083618593993744780613006909855561291409264101472678111564574885911922878664605690306182919070230365753921262106984244096437366083568935222012695178268484716429243802096196827183030384847796514876, + "P": 175377935666031786755660570177211436450380111907611958037824868372895755509356252779760511489824181767399092658930676404880297069685444401249659213519651777465351356257624143662039269347674022417059295938632797238737576256262492619014634593116323639243190104488935809108686384751566685806660124938811242086967, + "Q": 152023781514873764066792033033608257858574642149408621002545092265366219023343940012568303021165476501194468711036064003853040698031724773682328997857266108825409550549489307124453801052347026004322142693519620893289704513307824627929335189894580089058735382107841191849653244879342154112612269017108642531387 + }, + "NTildei": 21023415161514931930008466878652650089412402528643509910628555131344775794158903058369163761811104680637408260775817406933055101010078991353396708217239037610233406117989518964013955011431080536807756409589947737202805118447588754169619286059698346051434091526828610571256569564316417206639754298477685122805196892545615440112815631041008856187402317846173311204065893967539845566294007612545439663167301168890866914939671778637205312132294532685315455932227400848361283874655576282211589317437552929837915998820178547855772090057657134811218804757425834628549242669619312730165527727457922474374280635157012741361209, + "H1i": 15979859313395924571136148658272103938372277132678070185656328850555896690427265186126096171639291520357543524640425266307151982122049738808878264598206966080587709927906640387690608389668186869839953216402923927311693256889408989039177076903229553524022584907025308354010118759972205358791799330465993061080674460161824303321464792470295872129368382651158459686051383364336871730382257897383932053325036660618259973470074406164509122280382806650979917102193169315068112754326032498816760991618157715715214277113518569408529477400645370240927498578586798012381303913527260707011044009693067387622301641474678395137329, + "H2i": 3400219648626288789150267120389048671267876921097003637711074790973923585477139459215094640694084818158709978728077773527739904169606855197009342752699579884503899304360366963897162013108287406627863971362707752177726116720656411659548257360888026075554702014751238507746228702218843730081158778530747745587464924323563571971913669234138584348692135379073299032519767567815652599967281170018766276696019988439613999125787928364730268505921162016602516668092456347174784869553284192504853105190328240700628108541064081470312014006840605805807285843833534147866212446550895330114210814547493004700634134045261243609420, + "Alpha": 10968084746086553879555246005424151631351945362314644680429246279594619086481795490547770180177027337113479028220389082798572900071861443392448200276763503520560570427376023664716261778346234793033318073939745692127585713547475721641639705909319359058355835178573077774609782274457065790510114936006768976361662915708121382170755739592153979184713454213787772401345289335766812572968205368892968051801976644842791896044727706004497595735228077972228818633364818209488350957555438529541613073805942105414887874265488894469092510691335607804596893430423973847218866728459062319877402779773676930256597033350909593897945, + "Beta": 4275986465085912602037038190327168359940626612036952399077678882598121317075561451133118801920701359393828994187712811017932749085062721547706635260968141883926771954712872992294573300108782888432896766100565617540374111063873481445338754244281379709596250455026711325789081804317786986068893800559050584535395810581825654350383867621090683723404403296575545798254452059294793925405326587070269270774744714221418658615411917205850494208011064950146030237929039855940802955292868768908855211222004231747079914517136844476197364466479511494871033079340153339044310059993514529956706020475493216780800917573130241435107, + "P": 69476258668741688038577594919664335876905956586938543487896755788206168993897374629866752957331374026733148356008828420692573092081939761440587391514133910645127582786313219772844461665579743048731026561147450839535618160932594992418611075327388853616167168821845022924459985596452501813437755246921203218733, + "Q": 75649637604095871594471693631437284044569282038823214786757005709098971966306634567539461475248702621561583542981284049560600135882386712911786807118538860634013836828376264489830737293835498161381910332709274417066550695521467864502293556051033378667320092896496144727480670018979493247240881289654452764413 + }, + { + "PaillierSK": { + "N": 24052481522962876052360953346019440610188773160602387025048492823110532262773949490277423529395071335547527231561218901912183314499581635091149893746299506690057079443311927011121873860618042943963696483289967501741406838739673986526527440412352894606624268387963632920657975946786052527718342817803500056981867295297565008730358546052203974805316883404812822240385668096575271128598233183884330769588801518223928499989130081194410782399103427613109533112972374254439787046430963112599914990562447714115880755505990672481181189129691386186575437803399078059410905030250809446251354774414307498622695985998962151777661, + "LambdaN": 12026240761481438026180476673009720305094386580301193512524246411555266131386974745138711764697535667773763615780609450956091657249790817545574946873149753345028539721655963505560936930309021471981848241644983750870703419369836993263263720206176447303312134193981816460328987973393026263859171408901750028490778079419704517561722204670476010700428348702936799250029063085482068058802362283770023080631467066196295454957049844258347417091208189681961690693100734894148208732084181959095352415846890629309643658661929229804843619696068112637043032894208588825519259562494733181881254395863290773220136287817659733196526, + "PhiN": 24052481522962876052360953346019440610188773160602387025048492823110532262773949490277423529395071335547527231561218901912183314499581635091149893746299506690057079443311927011121873860618042943963696483289967501741406838739673986526527440412352894606624268387963632920657975946786052527718342817803500056981556158839409035123444409340952021400856697405873598500058126170964136117604724567540046161262934132392590909914099688516694834182416379363923381386201469788296417464168363918190704831693781258619287317323858459609687239392136225274086065788417177651038519124989466363762508791726581546440272575635319466393052, + "P": 143361985778015155255717551936923351473978017172304289042514220757059700028335455085828576502862530627104624322282919374840443445734819842795534922000993904620908353983877764688477404256971873407059086532102626198017920248257036511630382965980596012545444437988112039123267439451156170390211842842795458644363, + "Q": 167774472377958451658419159315030052986207981766919451285027704854075310965173161258456031823004855204232965752747473302875504770952228406390616804769910561522461228278721429720732754611694582089534351650029586673476029489298124400858989049001304395826941467273231043365578543236569781792211567520847226740247 + }, + "NTildei": 28495126655757486667458758522417879908145225138354011756695010310230080843775810691475508475189296932048204405538269234421309761999801641929339698921549089123747487722383263763650748100682062308320985638751456070929390702185959886711286692830051395068835285369347464130652877447989491271831963284492875520804370323467682501001588488044404416399192709674700712048722419143089138256847841944162078218754909772083880798045725064834323189904527799781096814998522360671548233319610818087987495141065235350701796581438153247939692152277023749182901393787894844691359824946779571324097127401565736630547441431638107656293181, + "H1i": 28139204291736107581049547396165574863203234868282840343850475611316742281564952788511685665677202050956468636410612105292574914465434643437843536369499800973537255887468353922417457678554017111438981470025595971749690307187278367116499631220803915226465968187669153053419544887620086914071454919928871241158300708745494285279416823564052160722164817586912567257185619724260285349040459813098794960371406943099932478046860993247998640963947483501215188172267462681319793590454634110086853775351617557697057810522572588207414329609572696435247631910943969381789031696553152361619843583633492290532183651674932213793892, + "H2i": 18343012511728251152619273706563580107510983295836399283735757723908485525490953893654379011407161304401117417774076488232861803078647038728469577888266739586943256069684503651055461129018569812210376305552773590891152511820448669598841281506429101111309136225768510573139029468583102907541234250967601742438791471921912179677553585666437013724159880990846845788805031792541045321076580789423919030557731118498588308112703684225304436096670649567207199927694259713849005362656595679403797591514253615426557419641322457053452553097223033051279368579757091249705121495314693330896281903365995694137463060183428898198895, + "Alpha": 15330324895839015629749164127055887108944620243211969987449311969454718352088715974341715252084527967431448134646088538144420853512995416273561618732151484903387355022214943735562071551195740107272138532892172113447845492301731674107910459116712851894480660771113461325203036787434742017215150159527872851126730784650009572323695990492300938571809441720444844601347874407418810527702088091020403934561398373419763402833712691730366310455834664292087593557723172758408828284194227131181575666576412848989757601500842237719690269216451865612174339505104169377221217624930504464413569272829312165764535900058466357572390, + "Beta": 1584804323870892662282706835809123240745461685457525841169702095713608517862442308385821550763247054160223993296163879255563530547139352807199871660462636080555894933373242237257723943484371130735538117066453264871610226674566607357030611411397696127526175338557535242927809949940694042389710283972054610301710349844906988403489741042387287668480277606438943930436243402434875142851991181176503058870337350050444131908536152285827112289950892735617965743934215843566437456037014148930468520915817894258024507411544349768951685233872346797375358616829119999319099828312162597921883543028221158582453429488858083709857, + "P": 84950601201178680727694881016637427640675160632220282849163482823997997624811703349976210542139670000850013753141650724543288468187042649202717339153218135793741655889877785431096531556507754254442924898238183920841803363232817140180008085098652654853071998322801343026310321567988075383000517691452076606659, + "Q": 83857931117743872301069013225213543854875205565418243931239291845157017247103778701694700849014042740796258819941830440731676813621100540961221084761025112092067689163962852285080221440034517787418977393812057026030822736805440919832827043894694378993424330632939046396206297815473996517457979684443043156749 + }, + { + "PaillierSK": { + "N": 28532083390186780519280501648721793129467844011498892536321043231855805410525503292096724543106431760326881112668992270200631197658215906941153806681817268863741858185487459659769348325078369392105144502823812902999129783542213853693259844069370505695481980103201086263132087207888270781551594469104238264488722908308751351423812207730579513284516868030187797994774171885991073257793492834857578371655897507676075586723447601741640197909930741428153757604093402647706619676570312196526983651713282712968671768369679862403878137205778316574735693551319153062000460655429895155942504997817787890847396211076822901784581, + "LambdaN": 14266041695093390259640250824360896564733922005749446268160521615927902705262751646048362271553215880163440556334496135100315598829107953470576903340908634431870929092743729829884674162539184696052572251411906451499564891771106926846629922034685252847740990051600543131566043603944135390775797234552119132244192287698227136022313780702650016000992398925068563143220558970429168692627477543116924614551673124866260635793794207570681174997235568732218257150735724569275482004567571417817282327186182657848329645786567178961556214732909321449820592389214182098253555346219400630541016873385239191498208412926667707247526, + "PhiN": 28532083390186780519280501648721793129467844011498892536321043231855805410525503292096724543106431760326881112668992270200631197658215906941153806681817268863741858185487459659769348325078369392105144502823812902999129783542213853693259844069370505695481980103201086263132087207888270781551594469104238264488384575396454272044627561405300032001984797850137126286441117940858337385254955086233849229103346249732521271587588415141362349994471137464436514301471449138550964009135142835634564654372365315696659291573134357923112429465818642899641184778428364196507110692438801261082033746770478382996416825853335414495052, + "P": 178397192612604798526968290931294714501451132274433804082417650074685738489897228727793893982225225752546520687942691828749089572044809494101838651319357498350212052895901283392803214993660904200357018761843124999768174912124384047979406690868733945683187341307267400295206865581696902698498782880780293418027, + "Q": 159935719684474580657678034348186568030619047776237904250636295058050134048640519895935248570326032191007794447916494771528758343414794469615404651302596010805443614539268077499615782347256493071655458034702379480997532827835289627115102082022054919810162621683826494565264385465612605152480602342707193871503 + }, + "NTildei": 26733289920026365778492885647254460326189033900698045325878057693985834595606177527651925592751912533688289358811198236988558779803498932755962261335119977382879838118872049616532997223764282759238906274176746425781577330531540107005260467055435414330514150021447276532181975314736550975239920227482389984722322579308534711831900966819220456144137887514935479109302466481476623097815121673104249856435477007435919192956671578798369291760464153531184470673674358246537004490313923351679993019195792761859368211433162663418187477894690176237777206320829181657018815385414525999759892853853566230626251256122415379372273, + "H1i": 20200543952388709836743372877597237406943839896347747383212226636682579390266700597516989020052810659597285482842863107076855223507089169031625149501738327365377781000351094672136173619680418109058858410399178590854493961183919089388663926099027471020358277104027668430773796084643496915015366640313310406276341135477922566455007610964540575699183201893462143061658856152480416538043586984610654740317757780453423860977037150598661267662470571960792850872798222793180041549984494604484570404209309244734823616789953164633842532577002860321511616983711280573990669660555250087063103648291591101220045659028218328100956, + "H2i": 10011436944148999704464729478673561825330402052836383319764735936166653136794101837350208534508492332341341255965887981883803557324617591767191078500745728335718952176480235872384811844719845355637797106611028176253832039374252087544755039245396420549730559767508655771782302883449821573989466800538465631076744692643173821046022994406780555158980770756763482451242912479953939932777447178637115678143977047057716538247771280467984161676537129369878726903024915919667830804872470049046316943500229610935124696240719749606229887055456619311751010965234390942106512645535387078751015648502532133358344733101213575772732, + "Alpha": 15565436498311155112588249022821862520831375916928397435754535386877538566831991068953160110964367946591299485137968199245528685773874438629821319030568442020250031560538582849448617250539719821910279322962449191452271999059043350678608792762537434805626510336661264707694517631088713862394614612816487271259264251433918921035494541091761245802760144441019786785426300945977040679290824987341086329162816295495152796652752825841845446501173445259521050149562516359758631274842233544201310219913069987127893273202943549304158659063779323230282264917107397543995383601760295260172143331759309750377027464738611257734556, + "Beta": 3883940474746516653806520604722516014415511103852633009581932326244372262855908107481901854763864126060702763451703384991981727435141718894619578305082311541038582671470968661787464939754228927702599076508120205169006314991280457956565876710934694218356058640551897261055991046770978180843036445234185579582345903284236515859517484716034054747281057931255577073243118208370448587951507091942552174494547468025928158407723447011390748139792263947401625790925853148867805209194434938388139467180472257196036659617838392275430990913650256930599038015752735092722456977368748464845214179352136934855551311384685460244367, + "P": 88168130008404525570080700707103177440944367692305190140628151484436185265313682857334978033182046126756391709077961850645380317710759458144830875967861656144788225571162087620278111559981354160418480933560535964383989980107742493600211919122200727043573677532742832571945019097078697284347853182975980385653, + "Q": 75802021426217289822102079905729104809367514694283311880419363873595399488548968787217821908097262719839159908360383891791627768255826891968397183231757256441595750371220484881193527416981015775805677238811550999891265011630635966369776465629277030122077586637094353538177149941931293814240150871910595472969 + }, + { + "PaillierSK": { + "N": 26996640296300651415400498554401486137947845822254251887766916948226349613131632612732250222343209672211664304457350856416313173796997278128216054444054531101181996295277761291573895534184826657300078523433362006179536527761026593314939857983859899807879337182885316022770084078937119713759957978793209959321773558388531252778985777267232264523363283291777180822279473099246650733627006953857220660330089524556812367404172433334239055657616263358739798733423460431363276818010096360055425692099023422440987119348965576326344453013140311995841156056046100731017938538439336584387442062457183076226558611796036832603917, + "LambdaN": 13498320148150325707700249277200743068973922911127125943883458474113174806565816306366125111171604836105832152228675428208156586898498639064108027222027265550590998147638880645786947767092413328650039261716681003089768263880513296657469928991929949903939668591442658011385042039468559856879978989396604979660722342895912497036521394673614697081030521511819274404285369261080473923995316551810539734496685124647636628742007298357742572095392117349769020737898095493776613311158059341001587427820508436790485543414473817465102062746820886491367913498519251718054955493855959951603808229326323526028511694853429746146238, + "PhiN": 26996640296300651415400498554401486137947845822254251887766916948226349613131632612732250222343209672211664304457350856416313173796997278128216054444054531101181996295277761291573895534184826657300078523433362006179536527761026593314939857983859899807879337182885316022770084078937119713759957978793209959321444685791824994073042789347229394162061043023638548808570738522160947847990633103621079468993370249295273257484014596715485144190784234699538041475796190987553226622316118682003174855641016873580971086828947634930204125493641772982735826997038503436109910987711919903207616458652647052057023389706859492292476, + "P": 157905148394759100940661864300050564272121208960007256882238286839980193380764286575055981798858297695053183016801509876409424866294884395357392006776721650508036186041981370664938186323116873237278846002699640274839145482649991664889544965563098882935710106691573689155912402662654496699699038906112143322839, + "Q": 170967448311499605002326055702819797030119059178624756826496290245722692255609563661085209537860977566485926903356326742344486600537144263844365250850547793302014009651996307387312650134889675622737186517318301121301182036848547348215784093444498411972317444035842992023913201141881527469836183183065196988603 + }, + "NTildei": 22436061566505115400255364934206443514880121947326950289482693221702208610753589741635209396952016373091555079648000236956995723851771160867556885395156505824344051167260809392148181658491568955113664358234083709771490930482313936184041101703657962234454203064371095370697130577170623689309659082800556686989285401665635869590761592643659123627663975825165592363434104158359403232225674866770531989356076225150418301435942369309478628288044705111511133055753831395876575155226508558182640100683925441038184263158472000921072850578784476359636108643340599841481197255164343314382678422505049162325472333625389562931577, + "H1i": 1199533861400575692856681402875292641734445351049563751937381586786477850751339951730561029476059139435535136420766353716253652623959385490555012010952213339410149494917020405689897932714018837946028125059091076013670791455394598890225844605686738602846173424436744756985469959258897687442804987490208370486068841656661510129964860544533440485303815470015661572402917804294333537516509746860702225007831407081975310947327910357478374447435164140164563121806197423582324070051275347417046411444337671579348228702122342464271403333762205833314842533725503951317809843463689279836236681777422863958847719655200665113697, + "H2i": 13975318898659837800412782768896011209985361726089775423824545800209227616884631073198171871883509581761333410095276918044890427119892906583746887329139403552379899531197309892138579515482522906489928976492442700099383674999002671192437729288280570458900729667558341917187130696878318333857273458025956269073592409661111143280330222888669910108452967384467607956021808171117737779006368835341901925347805963951029264904748092973628455762574918478477835335047063922027885012324366725886796945118396831977791108363699233412147104604560958899333031670818830779452001144139308962969607201086231581935024723793409846975956, + "Alpha": 7839871763817937648281508585771302168929438757070927924687782490100206714077674159655813164749073436760189220160719088320191721883374726294445050149155257503084546639744065102281188791160371649613509716336894750723421118393299089348711808142885248290365889240940587668495901911421541811175413308480394142999149048504367580084950000517351744315316986638974578499809054006704919313577480039567568168523993731975610844099512385233001358794335198157064809404551699357948747484230034228066907012460434902840508195179312607447867351440943484605479326566206818018968111409712608800887939979156700703436384338851571345319120, + "Beta": 455800020114336955047130350973908643968328619658648588284490242522854443889155886353368944844265827442470164696971726435102432811704767203050650599031223115644956163891750427472852265371320538935861137038980318883977212529964675222874366812637594065992186197548836529257983481168102743315233774248355356379282636239666047779224281459908779764056063684259221434607229600973188419803850680781307469601395038817459618625139046409207026317585277284165495620012660779577229570630797987283289009090561614707153014706263396359865315756090284423936957661245285858481179837641828947562030677390211533826134265382656454644752, + "P": 68316017966226044203323749387426902594489517305802024236273332367317700374032653511484870688184356264284841569881511332461005356624315345900612836543970100541105886547528423917928311100707782826904932690977668649249929795320653366466431337983769579326611029573726938313698391628000620296807273780702069610711, + "Q": 82103956855319849872216320654041726343405442413793796529484052448206141681339480943464447078010886607002703142238693643490834237742902859271062327382979840371867993179940812439698651194351239806544962334234075346850558367107330458640769005325621377862833899110675064788082408737470330896447881745451142755499 + } +] diff --git a/tss-lib/testutil/testutil.go b/tss-lib/testutil/testutil.go new file mode 100644 index 0000000..367852c --- /dev/null +++ b/tss-lib/testutil/testutil.go @@ -0,0 +1,51 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +// Package testutil provides pre-computed Paillier preparams for test +// use. Generating safe primes from scratch takes minutes per party; +// this fixture eliminates that cost from CI. +package testutil + +import ( + "encoding/json" + "testing" + + _ "embed" + + "github.com/hemilabs/x/tss-lib/v3/ecdsa/keygen" +) + +//go:embed preparams.json +var embeddedPreParams []byte + +var cachedParams []keygen.LocalPreParams + +func allParams(t *testing.T) []keygen.LocalPreParams { + t.Helper() + if cachedParams != nil { + return cachedParams + } + if err := json.Unmarshal(embeddedPreParams, &cachedParams); err != nil { + t.Fatalf("parse embedded preparams: %v", err) + } + return cachedParams +} + +// LoadPreParams returns n pre-computed LocalPreParams from the +// embedded fixture starting at index 0. +func LoadPreParams(t *testing.T, n int) []keygen.LocalPreParams { + return LoadPreParamsFrom(t, 0, n) +} + +// LoadPreParamsFrom returns n pre-computed LocalPreParams starting +// at the given offset. Use distinct offsets when old and new +// committees need non-overlapping preparams (e.g. resharing tests). +func LoadPreParamsFrom(t *testing.T, offset, n int) []keygen.LocalPreParams { + t.Helper() + params := allParams(t) + if offset+n > len(params) { + t.Fatalf("need preparams[%d:%d], fixture has %d", offset, offset+n, len(params)) + } + return params[offset : offset+n] +} diff --git a/tss-lib/tss/curve.go b/tss-lib/tss/curve.go index 983a936..e550ecf 100644 --- a/tss-lib/tss/curve.go +++ b/tss-lib/tss/curve.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package tss @@ -15,6 +14,7 @@ import ( "github.com/decred/dcrd/dcrec/edwards/v2" ) +// CurveName is a registered name for an elliptic curve. type CurveName string const ( @@ -33,9 +33,10 @@ func init() { registry = make(map[CurveName]elliptic.Curve) registry[Secp256k1] = s256k1.S256() - registry[Ed25519] = edwards.Edwards() + registry[Ed25519] = edwardsCurve } +// RegisterCurve adds a named curve to the global registry. func RegisterCurve(name CurveName, curve elliptic.Curve) { registry[name] = curve } @@ -90,6 +91,12 @@ func S256() elliptic.Curve { return s256k1.S256() } +// edwardsCurve is cached because edwards.Edwards() allocates a new +// instance each call. ECPoint.Add uses pointer identity to check +// curve compatibility, so all Edwards points must share one instance. +var edwardsCurve = edwards.Edwards() + +// Edwards returns the Edwards25519 curve for EdDSA. func Edwards() elliptic.Curve { - return edwards.Edwards() + return edwardsCurve } diff --git a/tss-lib/tss/curve_test.go b/tss-lib/tss/curve_test.go new file mode 100644 index 0000000..5d4bfc9 --- /dev/null +++ b/tss-lib/tss/curve_test.go @@ -0,0 +1,107 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +import ( + "crypto/elliptic" + "testing" +) + +func TestEdwardsSingleton(t *testing.T) { + a := Edwards() + b := Edwards() + if a != b { + t.Fatal("Edwards() should return the same pointer") + } +} + +func TestS256(t *testing.T) { + c := S256() + if c == nil { + t.Fatal("S256 returned nil") + } + if c.Params().BitSize != 256 { + t.Fatalf("S256 BitSize: want 256, got %d", c.Params().BitSize) + } +} + +func TestECDefault(t *testing.T) { + c := EC() + if c == nil { + t.Fatal("EC returned nil") + } +} + +func TestSetCurve(t *testing.T) { + orig := EC() + defer SetCurve(orig) + + SetCurve(Edwards()) + if EC() != Edwards() { + t.Fatal("SetCurve did not change EC()") + } +} + +func TestSetCurveNilPanics(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("SetCurve(nil) should panic") + } + }() + SetCurve(nil) +} + +func TestRegisterCurveAndGet(t *testing.T) { + c := elliptic.P256() + RegisterCurve("test-p256", c) + + got, ok := GetCurveByName("test-p256") + if !ok || got != c { + t.Fatal("GetCurveByName failed for registered curve") + } + + _, ok = GetCurveByName("nonexistent") + if ok { + t.Fatal("GetCurveByName should return false for unknown curve") + } +} + +func TestGetCurveName(t *testing.T) { + name, ok := GetCurveName(S256()) + if !ok { + t.Fatal("GetCurveName failed for S256") + } + if name != Secp256k1 { + t.Fatalf("GetCurveName: want %s, got %s", Secp256k1, name) + } + + name, ok = GetCurveName(Edwards()) + if !ok { + t.Fatal("GetCurveName failed for Edwards") + } + if name != Ed25519 { + t.Fatalf("GetCurveName: want %s, got %s", Ed25519, name) + } + + _, ok = GetCurveName(elliptic.P384()) + if ok { + t.Fatal("GetCurveName should return false for unregistered curve") + } +} + +func TestSameCurve(t *testing.T) { + if !SameCurve(S256(), S256()) { + t.Fatal("SameCurve(S256, S256) should be true") + } + if !SameCurve(Edwards(), Edwards()) { + t.Fatal("SameCurve(Edwards, Edwards) should be true") + } + if SameCurve(S256(), Edwards()) { + t.Fatal("SameCurve(S256, Edwards) should be false") + } + if SameCurve(elliptic.P384(), S256()) { + t.Fatal("SameCurve with unregistered curve should be false") + } +} diff --git a/tss-lib/tss/error.go b/tss-lib/tss/error.go index 0583cb2..91f4a23 100644 --- a/tss-lib/tss/error.go +++ b/tss-lib/tss/error.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package tss @@ -19,27 +18,35 @@ type Error struct { culprits []*PartyID } +// NewError creates a TSS protocol error with round context and culprits. func NewError(err error, task string, round int, victim *PartyID, culprits ...*PartyID) *Error { return &Error{cause: err, task: task, round: round, victim: victim, culprits: culprits} } +// Unwrap returns the underlying error. func (err *Error) Unwrap() error { return err.cause } +// Cause returns the underlying error (alias for Unwrap). func (err *Error) Cause() error { return err.cause } +// Task returns the protocol name (e.g. "ecdsa-keygen"). func (err *Error) Task() string { return err.task } +// Round returns the round number where the error occurred. func (err *Error) Round() int { return err.round } +// Victim returns the party that detected the error. func (err *Error) Victim() *PartyID { return err.victim } +// Culprits returns the parties responsible for the error. func (err *Error) Culprits() []*PartyID { return err.culprits } +// Error returns a human-readable error string. func (err *Error) Error() string { if err == nil || err.cause == nil { return "Error is nil" } - if err.culprits != nil && len(err.culprits) > 0 { + if len(err.culprits) > 0 { return fmt.Sprintf("task %s, party %v, round %d, culprits %s: %s", err.task, err.victim, err.round, err.culprits, err.cause.Error()) } diff --git a/tss-lib/tss/error_test.go b/tss-lib/tss/error_test.go new file mode 100644 index 0000000..857209c --- /dev/null +++ b/tss-lib/tss/error_test.go @@ -0,0 +1,75 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +import ( + "errors" + "math/big" + "strings" + "testing" +) + +func TestNewErrorWithCulprits(t *testing.T) { + victim := NewPartyID("v", "V", big.NewInt(1)) + c1 := NewPartyID("c1", "C1", big.NewInt(2)) + c2 := NewPartyID("c2", "C2", big.NewInt(3)) + cause := errors.New("bad share") + + e := NewError(cause, "ecdsa-keygen", 3, victim, c1, c2) + + if e.Task() != "ecdsa-keygen" { + t.Fatalf("Task: want ecdsa-keygen, got %s", e.Task()) + } + if e.Round() != 3 { + t.Fatalf("Round: want 3, got %d", e.Round()) + } + if e.Victim() != victim { + t.Fatal("Victim mismatch") + } + if len(e.Culprits()) != 2 { + t.Fatalf("Culprits: want 2, got %d", len(e.Culprits())) + } + if !errors.Is(e.Unwrap(), cause) { + t.Fatal("Unwrap mismatch") + } + if !errors.Is(e.Cause(), cause) { + t.Fatal("Cause mismatch") + } + + s := e.Error() + if !strings.Contains(s, "culprits") { + t.Fatalf("Error() should contain 'culprits': %s", s) + } + if !strings.Contains(s, "bad share") { + t.Fatalf("Error() should contain cause: %s", s) + } +} + +func TestNewErrorWithoutCulprits(t *testing.T) { + victim := NewPartyID("v", "V", big.NewInt(1)) + e := NewError(errors.New("oops"), "eddsa-signing", 2, victim) + + s := e.Error() + if strings.Contains(s, "culprits") { + t.Fatalf("Error() without culprits should not contain 'culprits': %s", s) + } + if !strings.Contains(s, "round 2") { + t.Fatalf("Error() should contain round: %s", s) + } +} + +func TestErrorNilReceiver(t *testing.T) { + var e *Error + if e.Error() != "Error is nil" { + t.Fatalf("nil Error.Error(): %s", e.Error()) + } +} + +func TestErrorNilCause(t *testing.T) { + e := &Error{} + if e.Error() != "Error is nil" { + t.Fatalf("nil-cause Error.Error(): %s", e.Error()) + } +} diff --git a/tss-lib/tss/merge.go b/tss-lib/tss/merge.go new file mode 100644 index 0000000..0b2cfca --- /dev/null +++ b/tss-lib/tss/merge.go @@ -0,0 +1,17 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +// MergeMsgs copies non-nil entries from src into dst, preserving +// any entries (such as self-messages from a previous round) that +// are already set in dst. Using copy() instead would overwrite +// populated slots with nil when the source slice is sparse. +func MergeMsgs(dst, src []*Message) { + for j, m := range src { + if m != nil { + dst[j] = m + } + } +} diff --git a/tss-lib/tss/message.go b/tss-lib/tss/message.go index acb4a6e..81ecedb 100644 --- a/tss-lib/tss/message.go +++ b/tss-lib/tss/message.go @@ -1,169 +1,32 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package tss -import ( - "fmt" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" -) - -type ( - // Message describes the interface of the TSS Message for all protocols - Message interface { - // Type is encoded in the protobuf Any structure - Type() string - // The set of parties that this message should be sent to - GetTo() []*PartyID - // The party that this message is from - GetFrom() *PartyID - // Indicates whether the message should be broadcast to other participants - IsBroadcast() bool - // Indicates whether the message is to the old committee during re-sharing; used mainly in tests - IsToOldCommittee() bool - // Indicates whether the message is to both committees during re-sharing; used mainly in tests - IsToOldAndNewCommittees() bool - // Returns the encoded inner message bytes to send over the wire along with metadata about how the message should be delivered - WireBytes() ([]byte, *MessageRouting, error) - // Returns the protobuf message wrapper struct - // Only its inner content should be sent over the wire, not this struct itself - WireMsg() *MessageWrapper - String() string - } - - // ParsedMessage represents a message with inner ProtoBuf message content - ParsedMessage interface { - Message - Content() MessageContent - ValidateBasic() bool - } - - // MessageContent represents a ProtoBuf message with validation logic - MessageContent interface { - proto.Message - ValidateBasic() bool - } - - // MessageRouting holds the full routing information for the message, consumed by the transport - MessageRouting struct { - // which participant this message came from - From *PartyID - // when `nil` the message should be broadcast to all parties - To []*PartyID - // whether the message should be broadcast to other participants - IsBroadcast bool - // whether the message should be sent to old committee participants rather than the new committee - IsToOldCommittee bool - // whether the message should be sent to both old and new committee participants - IsToOldAndNewCommittees bool - } - - // Implements ParsedMessage; this is a concrete implementation of what messages produced by a LocalParty look like - MessageImpl struct { - MessageRouting - content MessageContent - wire *MessageWrapper - } -) +import "fmt" -var ( - _ Message = (*MessageImpl)(nil) - _ ParsedMessage = (*MessageImpl)(nil) -) - -// ----- // - -// NewMessageWrapper constructs a MessageWrapper from routing metadata and content -func NewMessageWrapper(routing MessageRouting, content MessageContent) *MessageWrapper { - // marshal the content to the ProtoBuf Any type - any, _ := anypb.New(content) - // convert given PartyIDs to the wire format - var to []*MessageWrapper_PartyID - if routing.To != nil { - to = make([]*MessageWrapper_PartyID, len(routing.To)) - for i := range routing.To { - to[i] = routing.To[i].MessageWrapper_PartyID - } - } - return &MessageWrapper{ - IsBroadcast: routing.IsBroadcast, - IsToOldCommittee: routing.IsToOldCommittee, - IsToOldAndNewCommittees: routing.IsToOldAndNewCommittees, - From: routing.From.MessageWrapper_PartyID, - To: to, - Message: any, - } -} - -// ----- // - -func NewMessage(meta MessageRouting, content MessageContent, wire *MessageWrapper) ParsedMessage { - return &MessageImpl{ - MessageRouting: meta, - content: content, - wire: wire, - } -} - -func (mm *MessageImpl) Type() string { - return string(proto.MessageName(mm.content)) -} - -func (mm *MessageImpl) GetTo() []*PartyID { - return mm.To -} - -func (mm *MessageImpl) GetFrom() *PartyID { - return mm.From -} - -func (mm *MessageImpl) IsBroadcast() bool { - return mm.wire.IsBroadcast -} - -// only `true` in DGRound2Message (resharing) -func (mm *MessageImpl) IsToOldCommittee() bool { - return mm.wire.IsToOldCommittee -} - -// only `true` in DGRound4Message (resharing) -func (mm *MessageImpl) IsToOldAndNewCommittees() bool { - return mm.wire.IsToOldAndNewCommittees -} - -func (mm *MessageImpl) WireBytes() ([]byte, *MessageRouting, error) { - bz, err := proto.Marshal(mm.wire.Message) - if err != nil { - return nil, nil, err - } - return bz, &mm.MessageRouting, nil -} - -func (mm *MessageImpl) WireMsg() *MessageWrapper { - return mm.wire -} - -func (mm *MessageImpl) Content() MessageContent { - return mm.content -} - -func (mm *MessageImpl) ValidateBasic() bool { - return mm.content.ValidateBasic() -} - -func (mm *MessageImpl) String() string { +// Message carries a round function's output: routing metadata + +// content. Content is an untyped interface{} — each round function +// knows the concrete type it produces, and consumers type-assert. +// +// Serialization is the caller's responsibility. The library does +// not prescribe a wire format. +type Message struct { + From *PartyID + To []*PartyID // nil = broadcast + IsBroadcast bool + IsToOldCommittee bool + IsToOldAndNewCommittees bool + Content interface{} +} + +// String returns a human-readable summary for logging. +func (m *Message) String() string { toStr := "all" - if mm.To != nil { - toStr = fmt.Sprintf("%v", mm.To) - } - extraStr := "" - if mm.IsToOldCommittee() { - extraStr = " (To Old Committee)" + if m.To != nil { + toStr = fmt.Sprintf("%v", m.To) } - return fmt.Sprintf("Type: %s, From: %s, To: %s%s", mm.Type(), mm.From.String(), toStr, extraStr) + return fmt.Sprintf("From: %s, To: %s, Broadcast: %v", m.From, toStr, m.IsBroadcast) } diff --git a/tss-lib/tss/message.pb.go b/tss-lib/tss/message.pb.go deleted file mode 100644 index 749b802..0000000 --- a/tss-lib/tss/message.pb.go +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.14.0 -// source: protob/message.proto - -package tss - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Wrapper for TSS messages, often read by the transport layer and not itself sent over the wire -type MessageWrapper struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Metadata optionally un-marshalled and used by the transport to route this message. - IsBroadcast bool `protobuf:"varint,1,opt,name=is_broadcast,json=isBroadcast,proto3" json:"is_broadcast,omitempty"` - // Metadata optionally un-marshalled and used by the transport to route this message. - IsToOldCommittee bool `protobuf:"varint,2,opt,name=is_to_old_committee,json=isToOldCommittee,proto3" json:"is_to_old_committee,omitempty"` // used only in certain resharing messages - // Metadata optionally un-marshalled and used by the transport to route this message. - IsToOldAndNewCommittees bool `protobuf:"varint,5,opt,name=is_to_old_and_new_committees,json=isToOldAndNewCommittees,proto3" json:"is_to_old_and_new_committees,omitempty"` // used only in certain resharing messages - // Metadata optionally un-marshalled and used by the transport to route this message. - From *MessageWrapper_PartyID `protobuf:"bytes,3,opt,name=from,proto3" json:"from,omitempty"` - // Metadata optionally un-marshalled and used by the transport to route this message. - To []*MessageWrapper_PartyID `protobuf:"bytes,4,rep,name=to,proto3" json:"to,omitempty"` - // This field is actually what is sent through the wire and consumed on the other end by UpdateFromBytes. - // An Any contains an arbitrary serialized message as bytes, along with a URL that - // acts as a globally unique identifier for and resolves to that message's type. - Message *anypb.Any `protobuf:"bytes,10,opt,name=message,proto3" json:"message,omitempty"` -} - -func (x *MessageWrapper) Reset() { - *x = MessageWrapper{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_message_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MessageWrapper) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MessageWrapper) ProtoMessage() {} - -func (x *MessageWrapper) ProtoReflect() protoreflect.Message { - mi := &file_protob_message_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MessageWrapper.ProtoReflect.Descriptor instead. -func (*MessageWrapper) Descriptor() ([]byte, []int) { - return file_protob_message_proto_rawDescGZIP(), []int{0} -} - -func (x *MessageWrapper) GetIsBroadcast() bool { - if x != nil { - return x.IsBroadcast - } - return false -} - -func (x *MessageWrapper) GetIsToOldCommittee() bool { - if x != nil { - return x.IsToOldCommittee - } - return false -} - -func (x *MessageWrapper) GetIsToOldAndNewCommittees() bool { - if x != nil { - return x.IsToOldAndNewCommittees - } - return false -} - -func (x *MessageWrapper) GetFrom() *MessageWrapper_PartyID { - if x != nil { - return x.From - } - return nil -} - -func (x *MessageWrapper) GetTo() []*MessageWrapper_PartyID { - if x != nil { - return x.To - } - return nil -} - -func (x *MessageWrapper) GetMessage() *anypb.Any { - if x != nil { - return x.Message - } - return nil -} - -// PartyID represents a participant in the TSS protocol rounds. -// Note: The `id` and `moniker` are provided for convenience to allow you to track participants easier. -// The `id` is intended to be a unique string representation of `key` and `moniker` can be anything (even left blank). -type MessageWrapper_PartyID struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Moniker string `protobuf:"bytes,2,opt,name=moniker,proto3" json:"moniker,omitempty"` - Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` -} - -func (x *MessageWrapper_PartyID) Reset() { - *x = MessageWrapper_PartyID{} - if protoimpl.UnsafeEnabled { - mi := &file_protob_message_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MessageWrapper_PartyID) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MessageWrapper_PartyID) ProtoMessage() {} - -func (x *MessageWrapper_PartyID) ProtoReflect() protoreflect.Message { - mi := &file_protob_message_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MessageWrapper_PartyID.ProtoReflect.Descriptor instead. -func (*MessageWrapper_PartyID) Descriptor() ([]byte, []int) { - return file_protob_message_proto_rawDescGZIP(), []int{0, 0} -} - -func (x *MessageWrapper_PartyID) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *MessageWrapper_PartyID) GetMoniker() string { - if x != nil { - return x.Moniker - } - return "" -} - -func (x *MessageWrapper_PartyID) GetKey() []byte { - if x != nil { - return x.Key - } - return nil -} - -var File_protob_message_proto protoreflect.FileDescriptor - -var file_protob_message_proto_rawDesc = []byte{ - 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x62, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, - 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x8c, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x57, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x62, 0x72, 0x6f, 0x61, 0x64, - 0x63, 0x61, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x42, 0x72, - 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x69, 0x73, 0x5f, 0x74, 0x6f, - 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x73, 0x54, 0x6f, 0x4f, 0x6c, 0x64, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x3d, 0x0a, 0x1c, 0x69, 0x73, 0x5f, 0x74, 0x6f, 0x5f, - 0x6f, 0x6c, 0x64, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x69, 0x73, - 0x54, 0x6f, 0x4f, 0x6c, 0x64, 0x41, 0x6e, 0x64, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x62, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, - 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x57, 0x72, 0x61, 0x70, - 0x70, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x79, 0x49, 0x44, 0x52, 0x04, 0x66, 0x72, 0x6f, - 0x6d, 0x12, 0x36, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, - 0x62, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x74, 0x73, 0x73, 0x6c, 0x69, 0x62, 0x2e, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e, 0x50, 0x61, - 0x72, 0x74, 0x79, 0x49, 0x44, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x45, 0x0a, 0x07, 0x50, 0x61, 0x72, - 0x74, 0x79, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2f, 0x74, 0x73, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_protob_message_proto_rawDescOnce sync.Once - file_protob_message_proto_rawDescData = file_protob_message_proto_rawDesc -) - -func file_protob_message_proto_rawDescGZIP() []byte { - file_protob_message_proto_rawDescOnce.Do(func() { - file_protob_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_protob_message_proto_rawDescData) - }) - return file_protob_message_proto_rawDescData -} - -var file_protob_message_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_protob_message_proto_goTypes = []interface{}{ - (*MessageWrapper)(nil), // 0: binance.tsslib.MessageWrapper - (*MessageWrapper_PartyID)(nil), // 1: binance.tsslib.MessageWrapper.PartyID - (*anypb.Any)(nil), // 2: google.protobuf.Any -} -var file_protob_message_proto_depIdxs = []int32{ - 1, // 0: binance.tsslib.MessageWrapper.from:type_name -> binance.tsslib.MessageWrapper.PartyID - 1, // 1: binance.tsslib.MessageWrapper.to:type_name -> binance.tsslib.MessageWrapper.PartyID - 2, // 2: binance.tsslib.MessageWrapper.message:type_name -> google.protobuf.Any - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_protob_message_proto_init() } -func file_protob_message_proto_init() { - if File_protob_message_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_protob_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MessageWrapper); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_protob_message_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MessageWrapper_PartyID); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protob_message_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_protob_message_proto_goTypes, - DependencyIndexes: file_protob_message_proto_depIdxs, - MessageInfos: file_protob_message_proto_msgTypes, - }.Build() - File_protob_message_proto = out.File - file_protob_message_proto_rawDesc = nil - file_protob_message_proto_goTypes = nil - file_protob_message_proto_depIdxs = nil -} diff --git a/tss-lib/tss/message_test.go b/tss-lib/tss/message_test.go new file mode 100644 index 0000000..10602c1 --- /dev/null +++ b/tss-lib/tss/message_test.go @@ -0,0 +1,79 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +import ( + "math/big" + "strings" + "testing" +) + +func TestMessageStringBroadcast(t *testing.T) { + from := NewPartyID("a", "A", big.NewInt(1)) + m := &Message{From: from, IsBroadcast: true} + s := m.String() + if !strings.Contains(s, "all") { + t.Fatalf("broadcast message String should contain 'all': %s", s) + } + if !strings.Contains(s, "Broadcast: true") { + t.Fatalf("broadcast message String should contain 'Broadcast: true': %s", s) + } +} + +func TestMessageStringP2P(t *testing.T) { + from := NewPartyID("a", "A", big.NewInt(1)) + to := NewPartyID("b", "B", big.NewInt(2)) + m := &Message{From: from, To: []*PartyID{to}} + s := m.String() + if strings.Contains(s, "all") { + t.Fatalf("P2P message String should not contain 'all': %s", s) + } +} + +func TestMergeMsgsBasic(t *testing.T) { + m1 := &Message{IsBroadcast: true} + m2 := &Message{IsBroadcast: false} + dst := make([]*Message, 3) + dst[0] = m1 // pre-existing + + src := make([]*Message, 3) + src[1] = m2 // only slot 1 set + + MergeMsgs(dst, src) + + if dst[0] != m1 { + t.Fatal("MergeMsgs should preserve existing dst[0]") + } + if dst[1] != m2 { + t.Fatal("MergeMsgs should copy src[1] into dst[1]") + } + if dst[2] != nil { + t.Fatal("MergeMsgs should not set dst[2] from nil src[2]") + } +} + +func TestMergeMsgsOverwrite(t *testing.T) { + old := &Message{IsBroadcast: true} + updated := &Message{IsBroadcast: false} + dst := []*Message{old} + src := []*Message{updated} + MergeMsgs(dst, src) + if dst[0] != updated { + t.Fatal("MergeMsgs should overwrite non-nil with non-nil") + } +} + +func TestPeerContextSetIDs(t *testing.T) { + ids1 := GenerateTestPartyIDs(3) + ids2 := GenerateTestPartyIDs(2) + ctx := NewPeerContext(ids1) + if len(ctx.IDs()) != 3 { + t.Fatalf("initial IDs: want 3, got %d", len(ctx.IDs())) + } + ctx.SetIDs(ids2) + if len(ctx.IDs()) != 2 { + t.Fatalf("after SetIDs: want 2, got %d", len(ctx.IDs())) + } +} diff --git a/tss-lib/tss/params.go b/tss-lib/tss/params.go index ee17759..af7c3c3 100644 --- a/tss-lib/tss/params.go +++ b/tss-lib/tss/params.go @@ -1,14 +1,14 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package tss import ( "crypto/elliptic" "crypto/rand" + "fmt" "io" "runtime" "time" @@ -24,10 +24,20 @@ type ( concurrency int safePrimeGenTimeout time.Duration // proof session info - nonce int + // [FORK] Changed from `nonce int` to `nonce uint`. Upstream uses signed int, + // which allows negative nonces that are nonsensical for a session counter and + // could produce ambiguous SSID encodings (negative two's-complement vs positive). + nonce uint // for keygen noProofMod bool noProofFac bool + noProofDLN bool // [FORK] Added: allows disabling DLN proofs when replaced by SNARK coverage + // ceremonyID binds SSID to a specific ceremony instance. + // Two concurrent ceremonies with the same parties produce + // different SSIDs because their ceremonyIDs differ. The + // nonce field is orthogonal: it tracks retry attempts of + // the same logical ceremony. + ceremonyID []byte // random sources partialKeyRand, rand io.Reader } @@ -45,7 +55,17 @@ const ( ) // Exported, used in `tss` client +// +// [FORK] Added parameter validation panics. Upstream silently accepts invalid +// partyCount/threshold (e.g., threshold >= partyCount), which violates the +// (t,n)-threshold assumption and leads to subtle failures deeper in the protocol. func NewParameters(ec elliptic.Curve, ctx *PeerContext, partyID *PartyID, partyCount, threshold int) *Parameters { + if partyCount < 1 { + panic(fmt.Sprintf("NewParameters: partyCount must be >= 1, got %d", partyCount)) + } + if threshold < 0 || threshold >= partyCount { + panic(fmt.Sprintf("NewParameters: threshold must be in [0, partyCount), got threshold=%d, partyCount=%d", threshold, partyCount)) + } return &Parameters{ ec: ec, parties: ctx, @@ -59,30 +79,37 @@ func NewParameters(ec elliptic.Curve, ctx *PeerContext, partyID *PartyID, partyC } } +// EC returns the elliptic curve for this protocol run. func (params *Parameters) EC() elliptic.Curve { return params.ec } +// Parties returns the peer context with all party IDs. func (params *Parameters) Parties() *PeerContext { return params.parties } +// PartyID returns this party's ID. func (params *Parameters) PartyID() *PartyID { return params.partyID } +// PartyCount returns the total number of parties. func (params *Parameters) PartyCount() int { return params.partyCount } +// Threshold returns the signing threshold (t in t+1-of-n). func (params *Parameters) Threshold() int { return params.threshold } +// Concurrency returns the parallelism level for proof verification. func (params *Parameters) Concurrency() int { return params.concurrency } +// SafePrimeGenTimeout returns the timeout for safe prime generation. func (params *Parameters) SafePrimeGenTimeout() time.Duration { return params.safePrimeGenTimeout } @@ -92,38 +119,95 @@ func (params *Parameters) SetConcurrency(concurrency int) { params.concurrency = concurrency } +// SetSafePrimeGenTimeout sets the timeout for safe prime generation. func (params *Parameters) SetSafePrimeGenTimeout(timeout time.Duration) { params.safePrimeGenTimeout = timeout } +// NoProofMod returns true if modular proof verification is disabled. func (params *Parameters) NoProofMod() bool { return params.noProofMod } +// NoProofFac returns true if factorization proof verification is disabled. func (params *Parameters) NoProofFac() bool { return params.noProofFac } +// [FORK] Added SSIDNonce getter/setter pair. Upstream has no SSID nonce +// mechanism; all ceremony attempts share the same session ID, enabling +// cross-attempt proof replay attacks. +func (params *Parameters) SSIDNonce() uint { + return params.nonce +} + +// SetSSIDNonce sets the session nonce for SSID domain separation. +// Each retry of a ceremony MUST use a distinct nonce to prevent +// cross-attempt proof replay. +func (params *Parameters) SetSSIDNonce(n uint) { + params.nonce = n +} + +// CeremonyID returns the ceremony identifier bound into the SSID. +func (params *Parameters) CeremonyID() []byte { + return params.ceremonyID +} + +// SetCeremonyID binds a ceremony identifier into the SSID hash. +// This distinguishes concurrent ceremonies that share the same +// parties, threshold, and curve. The caller MUST set this before +// starting any round. +func (params *Parameters) SetCeremonyID(id []byte) { + params.ceremonyID = id +} + +// NoProofDLN returns true if DLN proof verification is disabled. +func (params *Parameters) NoProofDLN() bool { + return params.noProofDLN +} + +// SetNoProofDLN disables DLN proof generation and validation. +// WARNING: Only use in on-chain SNARK mode where DLN proofs are +// replaced by a SNARK covering the same security properties. +func (params *Parameters) SetNoProofDLN() { + params.noProofDLN = true +} + +// SetNoProofMod disables MOD proof generation and validation. +// WARNING: This is for testing/development ONLY. Disabling MOD proofs in +// production removes a critical security check that prevents a malicious party +// from using a non-safe-prime Paillier modulus, which breaks the security +// assumptions of the GG18 protocol. Never use in production deployments. func (params *Parameters) SetNoProofMod() { params.noProofMod = true } +// SetNoProofFac disables FAC proof generation and validation. +// WARNING: This is for testing/development ONLY. Disabling FAC proofs in +// production removes a critical security check that proves the prover's +// Paillier key factors are sufficiently large, which is required for the +// MtA (multiplicative-to-additive) protocol's soundness. Never use in +// production deployments. func (params *Parameters) SetNoProofFac() { params.noProofFac = true } +// PartialKeyRand returns the randomness source for partial key generation. func (params *Parameters) PartialKeyRand() io.Reader { return params.partialKeyRand } +// Rand returns the randomness source for protocol operations. func (params *Parameters) Rand() io.Reader { return params.rand } +// SetPartialKeyRand sets the randomness source for partial key generation. func (params *Parameters) SetPartialKeyRand(rand io.Reader) { params.partialKeyRand = rand } +// SetRand sets the randomness source for protocol operations. func (params *Parameters) SetRand(rand io.Reader) { params.rand = rand } @@ -131,8 +215,17 @@ func (params *Parameters) SetRand(rand io.Reader) { // ----- // // Exported, used in `tss` client +// +// [FORK] Added newPartyCount/newThreshold validation panics, same rationale as +// NewParameters above. Upstream silently accepts invalid resharing parameters. func NewReSharingParameters(ec elliptic.Curve, ctx, newCtx *PeerContext, partyID *PartyID, partyCount, threshold, newPartyCount, newThreshold int) *ReSharingParameters { params := NewParameters(ec, ctx, partyID, partyCount, threshold) + if newPartyCount < 1 { + panic(fmt.Sprintf("NewReSharingParameters: newPartyCount must be >= 1, got %d", newPartyCount)) + } + if newThreshold < 0 || newThreshold >= newPartyCount { + panic(fmt.Sprintf("NewReSharingParameters: newThreshold must be in [0, newPartyCount), got newThreshold=%d, newPartyCount=%d", newThreshold, newPartyCount)) + } return &ReSharingParameters{ Parameters: params, newParties: newCtx, @@ -141,34 +234,47 @@ func NewReSharingParameters(ec elliptic.Curve, ctx, newCtx *PeerContext, partyID } } +// OldParties returns the peer context for the old committee. func (rgParams *ReSharingParameters) OldParties() *PeerContext { return rgParams.Parties() // wr use the original method for old parties } +// OldPartyCount returns the number of parties in the old committee. func (rgParams *ReSharingParameters) OldPartyCount() int { return rgParams.partyCount } +// NewParties returns the peer context for the new committee. func (rgParams *ReSharingParameters) NewParties() *PeerContext { return rgParams.newParties } +// NewPartyCount returns the number of parties in the new committee. func (rgParams *ReSharingParameters) NewPartyCount() int { return rgParams.newPartyCount } +// NewThreshold returns the new signing threshold. func (rgParams *ReSharingParameters) NewThreshold() int { return rgParams.newThreshold } +// [FORK] Append-aliasing fix: upstream does `append(old, newParties...)` directly, +// which can corrupt the OldParties backing array if old has spare capacity. We +// allocate a fresh slice before appending to avoid this aliasing corruption. func (rgParams *ReSharingParameters) OldAndNewParties() []*PartyID { - return append(rgParams.OldParties().IDs(), rgParams.NewParties().IDs()...) + old := rgParams.OldParties().IDs() + out := make([]*PartyID, len(old), len(old)+len(rgParams.NewParties().IDs())) + copy(out, old) + return append(out, rgParams.NewParties().IDs()...) } +// OldAndNewPartyCount returns the total unique party count across both committees. func (rgParams *ReSharingParameters) OldAndNewPartyCount() int { return rgParams.OldPartyCount() + rgParams.NewPartyCount() } +// IsOldCommittee returns true if this party is in the old committee. func (rgParams *ReSharingParameters) IsOldCommittee() bool { partyID := rgParams.partyID for _, Pj := range rgParams.parties.IDs() { @@ -179,6 +285,7 @@ func (rgParams *ReSharingParameters) IsOldCommittee() bool { return false } +// IsNewCommittee returns true if this party is in the new committee. func (rgParams *ReSharingParameters) IsNewCommittee() bool { partyID := rgParams.partyID for _, Pj := range rgParams.newParties.IDs() { diff --git a/tss-lib/tss/params_fork_test.go b/tss-lib/tss/params_fork_test.go new file mode 100644 index 0000000..796ce31 --- /dev/null +++ b/tss-lib/tss/params_fork_test.go @@ -0,0 +1,306 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +import ( + "math/big" + "reflect" + "testing" +) + +// --- NewParameters panic tests --- + +func TestNewParametersPanicsInvalidThreshold(t *testing.T) { + // threshold >= partyCount should panic + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("threshold >= partyCount should panic") + } + }() + NewParameters(S256(), ctx, pIDs[0], 3, 3) // threshold == partyCount + }() +} + +func TestNewParametersPanicsNegativeThreshold(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("negative threshold should panic") + } + }() + NewParameters(S256(), ctx, pIDs[0], 3, -1) + }() +} + +func TestNewParametersPanicsZeroPartyCount(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("zero partyCount should panic") + } + }() + NewParameters(S256(), ctx, pIDs[0], 0, 0) // partyCount < 1 + }() +} + +func TestNewParametersAcceptsValid(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + + func() { + defer func() { + if r := recover(); r != nil { + t.Fatalf("unexpected panic: %v", r) + } + }() + p := NewParameters(S256(), ctx, pIDs[0], 3, 1) + if p.PartyCount() != 3 { + t.Fatalf("got %v, want 3", p.PartyCount()) + } + if p.Threshold() != 1 { + t.Fatalf("got %v, want 1", p.Threshold()) + } + }() +} + +// --- NewReSharingParameters panic tests --- + +func TestNewReSharingParametersPanicsZeroNewPartyCount(t *testing.T) { + oldIDs := GenerateTestPartyIDs(3) + newIDs := GenerateTestPartyIDs(3, 3) + oldCtx := NewPeerContext(oldIDs) + newCtx := NewPeerContext(newIDs) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("zero newPartyCount should panic") + } + }() + NewReSharingParameters(S256(), oldCtx, newCtx, oldIDs[0], 3, 1, 0, 1) // newPartyCount=0 + }() +} + +func TestNewReSharingParametersPanicsInvalidNewThreshold(t *testing.T) { + oldIDs := GenerateTestPartyIDs(3) + newIDs := GenerateTestPartyIDs(3, 3) + oldCtx := NewPeerContext(oldIDs) + newCtx := NewPeerContext(newIDs) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("newThreshold >= newPartyCount should panic") + } + }() + NewReSharingParameters(S256(), oldCtx, newCtx, oldIDs[0], 3, 1, 3, 3) // newThreshold == newPartyCount + }() +} + +func TestNewReSharingParametersPanicsNegativeNewThreshold(t *testing.T) { + oldIDs := GenerateTestPartyIDs(3) + newIDs := GenerateTestPartyIDs(3, 3) + oldCtx := NewPeerContext(oldIDs) + newCtx := NewPeerContext(newIDs) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("negative newThreshold should panic") + } + }() + NewReSharingParameters(S256(), oldCtx, newCtx, oldIDs[0], 3, 1, 3, -1) // newThreshold=-1 + }() +} + +// --- SortPartyIDs panic tests --- + +func TestSortPartyIDsZeroKeyPanics(t *testing.T) { + ids := UnSortedPartyIDs{ + NewPartyID("p1", "P1", big.NewInt(1)), + NewPartyID("p2", "P2", big.NewInt(0)), // zero key + NewPartyID("p3", "P3", big.NewInt(3)), + } + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("zero key should panic") + } + }() + SortPartyIDs(ids) + }() +} + +func TestSortPartyIDsDuplicateKeyPanics_Fork(t *testing.T) { + ids := UnSortedPartyIDs{ + NewPartyID("p1", "P1", big.NewInt(5)), + NewPartyID("p2", "P2", big.NewInt(5)), // duplicate + NewPartyID("p3", "P3", big.NewInt(3)), + } + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatal("duplicate key should panic") + } + }() + SortPartyIDs(ids) + }() +} + +func TestSortPartyIDsAcceptsValid(t *testing.T) { + ids := UnSortedPartyIDs{ + NewPartyID("p1", "P1", big.NewInt(3)), + NewPartyID("p2", "P2", big.NewInt(1)), + NewPartyID("p3", "P3", big.NewInt(2)), + } + + sorted := SortPartyIDs(ids) + if len(sorted) != 3 { + t.Fatalf("got %v, want %v", len(sorted), 3) + } + // Should be sorted ascending by key + if sorted[0].KeyInt().Cmp(big.NewInt(1)) != 0 { + t.Fatalf("got %v, want %v", sorted[0].KeyInt().Cmp(big.NewInt(1)), 0) + } + if sorted[1].KeyInt().Cmp(big.NewInt(2)) != 0 { + t.Fatalf("got %v, want %v", sorted[1].KeyInt().Cmp(big.NewInt(2)), 0) + } + if sorted[2].KeyInt().Cmp(big.NewInt(3)) != 0 { + t.Fatalf("got %v, want %v", sorted[2].KeyInt().Cmp(big.NewInt(3)), 0) + } +} + +// --- OldAndNewParties aliasing fix test --- + +func TestOldAndNewPartiesNoAliasing(t *testing.T) { + oldIDs := GenerateTestPartyIDs(3) + newIDs := GenerateTestPartyIDs(3, 3) // start at index 3 + + oldCtx := NewPeerContext(oldIDs) + newCtx := NewPeerContext(newIDs) + + params := NewReSharingParameters(S256(), oldCtx, newCtx, oldIDs[0], 3, 1, 3, 1) + + // Save original old parties + oldBefore := make([]*PartyID, len(oldIDs)) + copy(oldBefore, oldIDs) + + // Call OldAndNewParties + combined := params.OldAndNewParties() + + // Verify combined has all 6 parties + if len(combined) != 6 { + t.Fatalf("got %v, want %v", len(combined), 6) + } + + // Verify old parties were not corrupted + for i, pid := range oldIDs { + if pid.KeyInt().Cmp(oldBefore[i].KeyInt()) != 0 { + t.Fatalf("old party %d key was corrupted by OldAndNewParties", i) + } + } +} + +// --- SSIDNonce uint test --- + +func TestSSIDNonceUint(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + p := NewParameters(S256(), ctx, pIDs[0], 3, 1) + + // Default nonce should be 0 + if !reflect.DeepEqual(uint(0), p.SSIDNonce()) { + t.Fatalf("got %v, want %v", p.SSIDNonce(), uint(0)) + } + + // Set and get + p.SetSSIDNonce(42) + if !reflect.DeepEqual(uint(42), p.SSIDNonce()) { + t.Fatalf("got %v, want %v", p.SSIDNonce(), uint(42)) + } + + // Large value (won't overflow uint) + p.SetSSIDNonce(^uint(0)) // max uint + if !reflect.DeepEqual(^uint(0), p.SSIDNonce()) { + t.Fatalf("got %v, want %v", p.SSIDNonce(), ^uint(0)) + } +} + +// --- PartyID ValidateBasic tests --- + +func TestPartyIDValidateBasicRejectsEmptyKey(t *testing.T) { + // [FORK] Upstream checks Key != nil but not len(Key) > 0. + // An empty byte slice passes nil check but KeyInt() returns 0. + pid := &PartyID{ + PartyIDData: &PartyIDData{ + Id: "test", + Moniker: "Test", + Key: []byte{}, // empty, not nil + }, + Index: 0, + } + if pid.ValidateBasic() { + t.Fatal("empty key should fail ValidateBasic") + } +} + +func TestPartyIDValidateBasicRejectsNilKey(t *testing.T) { + pid := &PartyID{ + PartyIDData: &PartyIDData{ + Id: "test", + Moniker: "Test", + Key: nil, + }, + Index: 0, + } + if pid.ValidateBasic() { + t.Fatal("nil key should fail ValidateBasic") + } +} + +func TestPartyIDValidateBasicAcceptsValid(t *testing.T) { + pid := NewPartyID("test", "Test", big.NewInt(42)) + pid.Index = 0 + if !pid.ValidateBasic() { + t.Fatal("valid party ID should pass") + } +} + +func TestPartyIDValidateBasicRejectsNegativeIndex(t *testing.T) { + pid := NewPartyID("test", "Test", big.NewInt(42)) + pid.Index = -1 // not yet sorted + if pid.ValidateBasic() { + t.Fatal("negative index should fail ValidateBasic") + } +} + +// --- SortedPartyIDs Less strict ordering --- + +func TestSortedPartyIDsLessIsStrict(t *testing.T) { + // [FORK] Upstream uses <= (treats equal as less-than), fork uses < (strict) + ids := SortedPartyIDs{ + NewPartyID("a", "A", big.NewInt(5)), + NewPartyID("b", "B", big.NewInt(5)), // same key + } + // With strict Less, neither should be "less than" the other + if ids.Less(0, 1) { + t.Fatal("equal keys: Less(0,1) should be false (strict)") + } + if ids.Less(1, 0) { + t.Fatal("equal keys: Less(1,0) should be false (strict)") + } +} diff --git a/tss-lib/tss/params_test.go b/tss-lib/tss/params_test.go new file mode 100644 index 0000000..429357a --- /dev/null +++ b/tss-lib/tss/params_test.go @@ -0,0 +1,194 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +import ( + "bytes" + "crypto/rand" + "math/big" + "testing" + "time" +) + +func TestParametersGetters(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + params := NewParameters(S256(), ctx, pIDs[0], 3, 1) + + if params.EC() != S256() { + t.Fatal("EC mismatch") + } + if params.PartyID() != pIDs[0] { + t.Fatal("PartyID mismatch") + } + if params.PartyCount() != 3 { + t.Fatalf("PartyCount: want 3, got %d", params.PartyCount()) + } + if params.Threshold() != 1 { + t.Fatalf("Threshold: want 1, got %d", params.Threshold()) + } + if params.Concurrency() < 1 { + t.Fatal("Concurrency should be >= 1") + } + if params.SafePrimeGenTimeout() == 0 { + t.Fatal("SafePrimeGenTimeout should have a default") + } + if params.PartialKeyRand() == nil { + t.Fatal("PartialKeyRand should default to non-nil") + } + if params.Rand() == nil { + t.Fatal("Rand should default to non-nil") + } +} + +func TestParametersSetters(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + params := NewParameters(S256(), ctx, pIDs[0], 3, 1) + + params.SetConcurrency(4) + if params.Concurrency() != 4 { + t.Fatalf("SetConcurrency: want 4, got %d", params.Concurrency()) + } + + params.SetSafePrimeGenTimeout(10 * time.Second) + if params.SafePrimeGenTimeout() != 10*time.Second { + t.Fatal("SetSafePrimeGenTimeout mismatch") + } + + customRand := bytes.NewReader(nil) + params.SetRand(customRand) + if params.Rand() != customRand { + t.Fatal("SetRand mismatch") + } + + params.SetPartialKeyRand(rand.Reader) + if params.PartialKeyRand() != rand.Reader { + t.Fatal("SetPartialKeyRand mismatch") + } +} + +func TestParametersProofFlags(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + params := NewParameters(S256(), ctx, pIDs[0], 3, 1) + + if params.NoProofMod() { + t.Fatal("NoProofMod should default to false") + } + if params.NoProofFac() { + t.Fatal("NoProofFac should default to false") + } + + params.SetNoProofMod() + if !params.NoProofMod() { + t.Fatal("SetNoProofMod did not set flag") + } + + params.SetNoProofFac() + if !params.NoProofFac() { + t.Fatal("SetNoProofFac did not set flag") + } +} + +func TestParametersCeremonyID(t *testing.T) { + pIDs := GenerateTestPartyIDs(3) + ctx := NewPeerContext(pIDs) + params := NewParameters(S256(), ctx, pIDs[0], 3, 1) + + if params.CeremonyID() != nil { + t.Fatal("CeremonyID should default to nil") + } + + cid := []byte("test-ceremony-42") + params.SetCeremonyID(cid) + if !bytes.Equal(params.CeremonyID(), cid) { + t.Fatal("SetCeremonyID mismatch") + } +} + +func TestReSharingParametersGetters(t *testing.T) { + oldPIDs := GenerateTestPartyIDs(3) + newPIDs := GenerateTestPartyIDs(4) + oldCtx := NewPeerContext(oldPIDs) + newCtx := NewPeerContext(newPIDs) + + params := NewReSharingParameters(S256(), oldCtx, newCtx, oldPIDs[0], 3, 1, 4, 2) + + if params.OldPartyCount() != 3 { + t.Fatalf("OldPartyCount: want 3, got %d", params.OldPartyCount()) + } + if params.NewPartyCount() != 4 { + t.Fatalf("NewPartyCount: want 4, got %d", params.NewPartyCount()) + } + if params.NewThreshold() != 2 { + t.Fatalf("NewThreshold: want 2, got %d", params.NewThreshold()) + } + if params.OldAndNewPartyCount() != 7 { + t.Fatalf("OldAndNewPartyCount: want 7, got %d", params.OldAndNewPartyCount()) + } +} + +func TestReSharingParametersCommitteeMembership(t *testing.T) { + oldPIDs := GenerateTestPartyIDs(3) + newPIDs := GenerateTestPartyIDs(3) + oldCtx := NewPeerContext(oldPIDs) + newCtx := NewPeerContext(newPIDs) + + // Old-only party + paramsOld := NewReSharingParameters(S256(), oldCtx, newCtx, oldPIDs[0], 3, 1, 3, 1) + if !paramsOld.IsOldCommittee() { + t.Fatal("oldPIDs[0] should be in old committee") + } + if paramsOld.IsNewCommittee() { + t.Fatal("oldPIDs[0] should NOT be in new committee") + } + + // New-only party + paramsNew := NewReSharingParameters(S256(), oldCtx, newCtx, newPIDs[0], 3, 1, 3, 1) + if paramsNew.IsOldCommittee() { + t.Fatal("newPIDs[0] should NOT be in old committee") + } + if !paramsNew.IsNewCommittee() { + t.Fatal("newPIDs[0] should be in new committee") + } +} + +func TestReSharingParametersOverlap(t *testing.T) { + allPIDs := GenerateTestPartyIDs(4) + copyPID := func(src *PartyID) *PartyID { + return NewPartyID(src.Id, src.Moniker, new(big.Int).SetBytes(src.Key)) + } + oldPIDs := SortPartyIDs(UnSortedPartyIDs{copyPID(allPIDs[0]), copyPID(allPIDs[1]), copyPID(allPIDs[2])}) + newPIDs := SortPartyIDs(UnSortedPartyIDs{copyPID(allPIDs[1]), copyPID(allPIDs[2]), copyPID(allPIDs[3])}) + oldCtx := NewPeerContext(oldPIDs) + newCtx := NewPeerContext(newPIDs) + + // P1 (allPIDs[1]) is in both committees + paramsDual := NewReSharingParameters(S256(), oldCtx, newCtx, allPIDs[1], 3, 1, 3, 1) + if !paramsDual.IsOldCommittee() { + t.Fatal("dual party should be in old committee") + } + if !paramsDual.IsNewCommittee() { + t.Fatal("dual party should be in new committee") + } +} + +func TestOldAndNewPartiesLength(t *testing.T) { + oldPIDs := GenerateTestPartyIDs(3) + newPIDs := GenerateTestPartyIDs(2) + oldCtx := NewPeerContext(oldPIDs) + newCtx := NewPeerContext(newPIDs) + + params := NewReSharingParameters(S256(), oldCtx, newCtx, oldPIDs[0], 3, 1, 2, 1) + all := params.OldAndNewParties() + if len(all) != 5 { + t.Fatalf("OldAndNewParties: want 5, got %d", len(all)) + } + // Verify no aliasing with OldParties + if len(params.OldParties().IDs()) != 3 { + t.Fatal("OldAndNewParties corrupted OldParties") + } +} diff --git a/tss-lib/tss/party.go b/tss-lib/tss/party.go deleted file mode 100644 index d28eb13..0000000 --- a/tss-lib/tss/party.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package tss - -import ( - "errors" - "fmt" - "sync" - - "github.com/hemilabs/x/tss-lib/v2/common" -) - -type Party interface { - Start() *Error - // The main entry point when updating a party's state from the wire. - // isBroadcast should represent whether the message was received via a reliable broadcast - UpdateFromBytes(wireBytes []byte, from *PartyID, isBroadcast bool) (ok bool, err *Error) - // You may use this entry point to update a party's state when running locally or in tests - Update(msg ParsedMessage) (ok bool, err *Error) - Running() bool - WaitingFor() []*PartyID - ValidateMessage(msg ParsedMessage) (bool, *Error) - StoreMessage(msg ParsedMessage) (bool, *Error) - FirstRound() Round - WrapError(err error, culprits ...*PartyID) *Error - PartyID() *PartyID - String() string - - // Private lifecycle methods - setRound(Round) *Error - round() Round - advance() - lock() - unlock() -} - -type BaseParty struct { - mtx sync.Mutex - rnd Round - FirstRound Round -} - -func (p *BaseParty) Running() bool { - return p.rnd != nil -} - -func (p *BaseParty) WaitingFor() []*PartyID { - p.lock() - defer p.unlock() - if p.rnd == nil { - return []*PartyID{} - } - return p.rnd.WaitingFor() -} - -func (p *BaseParty) WrapError(err error, culprits ...*PartyID) *Error { - if p.rnd == nil { - return NewError(err, "", -1, nil, culprits...) - } - return p.rnd.WrapError(err, culprits...) -} - -// an implementation of ValidateMessage that is shared across the different types of parties (keygen, signing, dynamic groups) -func (p *BaseParty) ValidateMessage(msg ParsedMessage) (bool, *Error) { - if msg == nil || msg.Content() == nil { - return false, p.WrapError(fmt.Errorf("received nil msg: %s", msg)) - } - if msg.GetFrom() == nil || !msg.GetFrom().ValidateBasic() { - return false, p.WrapError(fmt.Errorf("received msg with an invalid sender: %s", msg)) - } - if !msg.ValidateBasic() { - return false, p.WrapError(fmt.Errorf("message failed ValidateBasic: %s", msg), msg.GetFrom()) - } - return true, nil -} - -func (p *BaseParty) String() string { - if rnd := p.round(); rnd != nil { - return fmt.Sprintf("round: %d", rnd.RoundNumber()) - } - - return "No more rounds" -} - -// ----- -// Private lifecycle methods - -func (p *BaseParty) setRound(round Round) *Error { - if p.rnd != nil { - return p.WrapError(errors.New("a round is already set on this party")) - } - p.rnd = round - return nil -} - -func (p *BaseParty) round() Round { - return p.rnd -} - -func (p *BaseParty) advance() { - p.rnd = p.rnd.NextRound() -} - -func (p *BaseParty) lock() { - p.mtx.Lock() -} - -func (p *BaseParty) unlock() { - p.mtx.Unlock() -} - -// ----- // - -func BaseStart(p Party, task string, prepare ...func(Round) *Error) *Error { - p.lock() - defer p.unlock() - if p.PartyID() == nil || !p.PartyID().ValidateBasic() { - return p.WrapError(fmt.Errorf("could not start. this party has an invalid PartyID: %+v", p.PartyID())) - } - if p.round() != nil { - return p.WrapError(errors.New("could not start. this party is in an unexpected state. use the constructor and Start()")) - } - round := p.FirstRound() - if err := p.setRound(round); err != nil { - return err - } - if 1 < len(prepare) { - return p.WrapError(errors.New("too many prepare functions given to Start(); 1 allowed")) - } - if len(prepare) == 1 { - if err := prepare[0](round); err != nil { - return err - } - } - common.Logger.Infof("party %s: %s round %d starting", p.round().Params().PartyID(), task, 1) - defer func() { - common.Logger.Debugf("party %s: %s round %d finished", p.round().Params().PartyID(), task, 1) - }() - return p.round().Start() -} - -// an implementation of Update that is shared across the different types of parties (keygen, signing, dynamic groups) -func BaseUpdate(p Party, msg ParsedMessage, task string) (ok bool, err *Error) { - // fast-fail on an invalid message; do not lock the mutex yet - if _, err := p.ValidateMessage(msg); err != nil { - return false, err - } - // lock the mutex. need this mtx unlock hook; L108 is recursive so cannot use defer - r := func(ok bool, err *Error) (bool, *Error) { - p.unlock() - return ok, err - } - p.lock() // data is written to P state below - common.Logger.Debugf("party %s received message: %s", p.PartyID(), msg.String()) - if p.round() != nil { - common.Logger.Debugf("party %s round %d update: %s", p.PartyID(), p.round().RoundNumber(), msg.String()) - } - if ok, err := p.StoreMessage(msg); err != nil || !ok { - return r(false, err) - } - if p.round() != nil { - common.Logger.Debugf("party %s: %s round %d update", p.round().Params().PartyID(), task, p.round().RoundNumber()) - if _, err := p.round().Update(); err != nil { - return r(false, err) - } - if p.round().CanProceed() { - if p.advance(); p.round() != nil { - if err := p.round().Start(); err != nil { - return r(false, err) - } - rndNum := p.round().RoundNumber() - common.Logger.Infof("party %s: %s round %d started", p.round().Params().PartyID(), task, rndNum) - } else { - // finished! the round implementation will have sent the data through the `end` channel. - common.Logger.Infof("party %s: %s finished!", p.PartyID(), task) - } - p.unlock() // recursive so can't defer after return - return BaseUpdate(p, msg, task) // re-run round update or finish) - } - return r(true, nil) - } - return r(true, nil) -} diff --git a/tss-lib/tss/party_id.go b/tss-lib/tss/party_id.go index 8c34b26..c098767 100644 --- a/tss-lib/tss/party_id.go +++ b/tss-lib/tss/party_id.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package tss @@ -12,15 +11,26 @@ import ( "math/big" "sort" - "github.com/hemilabs/x/tss-lib/v2/common" + "github.com/hemilabs/x/tss-lib/v3/common" ) +// PartyIDData holds the wire-format fields for a party identifier. +// Replaces the protobuf MessageWrapper_PartyID. +type PartyIDData struct { + Id string `json:"id"` + Moniker string `json:"moniker"` + Key []byte `json:"key"` +} + +// KeyInt returns the party key as a *big.Int. +func (d *PartyIDData) KeyInt() *big.Int { + return new(big.Int).SetBytes(d.Key) +} + type ( // PartyID represents a participant in the TSS protocol rounds. - // Note: The `id` and `moniker` are provided for convenience to allow you to track participants easier. - // The `id` is intended to be a unique string representation of `key` and `moniker` can be anything (even left blank). PartyID struct { - *MessageWrapper_PartyID + *PartyIDData Index int `json:"index"` } @@ -28,46 +38,47 @@ type ( SortedPartyIDs []*PartyID ) +// ValidateBasic checks that the PartyID has a non-empty key and +// non-negative index. func (pid *PartyID) ValidateBasic() bool { - return pid != nil && pid.Key != nil && 0 <= pid.Index -} - -// --- ProtoBuf Extensions - -func (mpid *MessageWrapper_PartyID) KeyInt() *big.Int { - return new(big.Int).SetBytes(mpid.Key) + return pid != nil && len(pid.Key) > 0 && 0 <= pid.Index } -// ----- // - -// NewPartyID constructs a new PartyID -// Exported, used in `tss` client. `key` should remain consistent between runs for each party. +// NewPartyID constructs a new PartyID. func NewPartyID(id, moniker string, key *big.Int) *PartyID { return &PartyID{ - MessageWrapper_PartyID: &MessageWrapper_PartyID{ + PartyIDData: &PartyIDData{ Id: id, Moniker: moniker, Key: key.Bytes(), }, - Index: -1, // not known until sorted + Index: -1, } } +// String returns a human-readable representation of the party ID. func (pid PartyID) String() string { return fmt.Sprintf("{%d,%s}", pid.Index, pid.Moniker) } -// ----- // - -// SortPartyIDs sorts a list of []*PartyID by their keys in ascending order -// Exported, used in `tss` client +// SortPartyIDs sorts a list of []*PartyID by their keys in ascending +// order and validates no zero or duplicate keys. func SortPartyIDs(ids UnSortedPartyIDs, startAt ...int) SortedPartyIDs { sorted := make(SortedPartyIDs, 0, len(ids)) for _, id := range ids { sorted = append(sorted, id) } sort.Sort(sorted) - // assign party indexes + zero := big.NewInt(0) + for i := 0; i < len(sorted); i++ { + if sorted[i].KeyInt().Cmp(zero) == 0 { + panic(fmt.Sprintf("SortPartyIDs: party at index %d has Key=0; VSS evaluation at zero leaks the secret", i)) + } + if i > 0 && sorted[i-1].KeyInt().Cmp(sorted[i].KeyInt()) == 0 { + panic(fmt.Sprintf("SortPartyIDs: duplicate key at indices %d and %d (key=%s)", + i-1, i, sorted[i].KeyInt())) + } + } for i, id := range sorted { frm := 0 if len(startAt) > 0 { @@ -78,30 +89,30 @@ func SortPartyIDs(ids UnSortedPartyIDs, startAt ...int) SortedPartyIDs { return sorted } -// GenerateTestPartyIDs generates a list of mock PartyIDs for tests +// GenerateTestPartyIDs generates a list of mock PartyIDs for tests. func GenerateTestPartyIDs(count int, startAt ...int) SortedPartyIDs { ids := make(UnSortedPartyIDs, 0, count) key := common.MustGetRandomInt(rand.Reader, 256) frm := 0 - i := 0 // default `i` + i := 0 if len(startAt) > 0 { frm = startAt[0] i = startAt[0] } for ; i < count+frm; i++ { ids = append(ids, &PartyID{ - MessageWrapper_PartyID: &MessageWrapper_PartyID{ + PartyIDData: &PartyIDData{ Id: fmt.Sprintf("%d", i+1), Moniker: fmt.Sprintf("P[%d]", i+1), Key: new(big.Int).Sub(key, big.NewInt(int64(count)-int64(i))).Bytes(), }, Index: i, - // this key makes tests more deterministic }) } return SortPartyIDs(ids, startAt...) } +// Keys returns the big.Int keys of all party IDs in sorted order. func (spids SortedPartyIDs) Keys() []*big.Int { ids := make([]*big.Int, spids.Len()) for i, pid := range spids { @@ -110,10 +121,12 @@ func (spids SortedPartyIDs) Keys() []*big.Int { return ids } +// ToUnSorted returns the party IDs as an unsorted slice. func (spids SortedPartyIDs) ToUnSorted() UnSortedPartyIDs { return UnSortedPartyIDs(spids) } +// FindByKey returns the PartyID with the given key, or nil. func (spids SortedPartyIDs) FindByKey(key *big.Int) *PartyID { for _, pid := range spids { if pid.KeyInt().Cmp(key) == 0 { @@ -123,11 +136,12 @@ func (spids SortedPartyIDs) FindByKey(key *big.Int) *PartyID { return nil } +// Exclude returns a new sorted slice with the given party removed. func (spids SortedPartyIDs) Exclude(exclude *PartyID) SortedPartyIDs { newSpIDs := make(SortedPartyIDs, 0, len(spids)) for _, pid := range spids { if pid.KeyInt().Cmp(exclude.KeyInt()) == 0 { - continue // exclude + continue } newSpIDs = append(newSpIDs, pid) } @@ -135,15 +149,14 @@ func (spids SortedPartyIDs) Exclude(exclude *PartyID) SortedPartyIDs { } // Sortable +func (spids SortedPartyIDs) Len() int { return len(spids) } -func (spids SortedPartyIDs) Len() int { - return len(spids) -} - +// Less implements sort.Interface. func (spids SortedPartyIDs) Less(a, b int) bool { - return spids[a].KeyInt().Cmp(spids[b].KeyInt()) <= 0 + return spids[a].KeyInt().Cmp(spids[b].KeyInt()) < 0 } +// Swap implements sort.Interface. func (spids SortedPartyIDs) Swap(a, b int) { spids[a], spids[b] = spids[b], spids[a] } diff --git a/tss-lib/tss/party_id_test.go b/tss-lib/tss/party_id_test.go new file mode 100644 index 0000000..1cd7eb5 --- /dev/null +++ b/tss-lib/tss/party_id_test.go @@ -0,0 +1,517 @@ +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. + +package tss + +import ( + "fmt" + "math/big" + "testing" +) + +// --------------------------------------------------------------------------- +// Parameters accessor tests +// --------------------------------------------------------------------------- + +// TestParametersSSIDNonceAccessors verifies that SetSSIDNonce/SSIDNonce work +// correctly and that the default nonce is 0. +func TestParametersSSIDNonceAccessors(t *testing.T) { + pIDs := GenerateTestPartyIDs(2) + p2pCtx := NewPeerContext(pIDs) + params := NewParameters(S256(), p2pCtx, pIDs[0], 2, 1) + + // Default nonce should be 0. + if params.SSIDNonce() != 0 { + t.Fatalf("default SSIDNonce should be 0, got %d", params.SSIDNonce()) + } + + // Set and get. + params.SetSSIDNonce(42) + if params.SSIDNonce() != 42 { + t.Fatalf("SSIDNonce should be 42, got %d", params.SSIDNonce()) + } + + // Set to a different value. + params.SetSSIDNonce(999) + if params.SSIDNonce() != 999 { + t.Fatalf("SSIDNonce should be 999, got %d", params.SSIDNonce()) + } + + // Set back to 0. + params.SetSSIDNonce(0) + if params.SSIDNonce() != 0 { + t.Fatalf("SSIDNonce should be 0, got %d", params.SSIDNonce()) + } +} + +// TestParametersNoProofDLNAccessors verifies that SetNoProofDLN/NoProofDLN work +// correctly and that the default is false. +func TestParametersNoProofDLNAccessors(t *testing.T) { + pIDs := GenerateTestPartyIDs(2) + p2pCtx := NewPeerContext(pIDs) + params := NewParameters(S256(), p2pCtx, pIDs[0], 2, 1) + + // Default should be false. + if params.NoProofDLN() { + t.Fatal("default NoProofDLN should be false") + } + + // Set and get. + params.SetNoProofDLN() + if !params.NoProofDLN() { + t.Fatal("NoProofDLN should be true after SetNoProofDLN()") + } +} + +// --------------------------------------------------------------------------- +// PartyID tests +// --------------------------------------------------------------------------- + +// TestSortedPartyIDsLessEqualKeys verifies that Less() uses strict < (not <=), +// complying with the sort.Interface contract: Less(a,a) must be false. +func TestSortedPartyIDsLessEqualKeys(t *testing.T) { + sameKey := big.NewInt(42) + p1 := NewPartyID("p1", "Party1", sameKey) + p2 := NewPartyID("p2", "Party2", sameKey) + + spids := SortedPartyIDs{p1, p2} + + less01 := spids.Less(0, 1) + less10 := spids.Less(1, 0) + + // With strict <, neither direction should be true for equal keys. + if less01 { + t.Fatal("Less(0,1) should be false for equal keys") + } + if less10 { + t.Fatal("Less(1,0) should be false for equal keys") + } + // Also verify reflexivity: Less(a,a) must be false. + if spids.Less(0, 0) { + t.Fatal("Less(0,0) should be false (irreflexivity)") + } +} + +// TestSortedPartyIDsLessDistinctKeys verifies correct ordering for distinct keys. +func TestSortedPartyIDsLessDistinctKeys(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(1)) + p2 := NewPartyID("p2", "Party2", big.NewInt(2)) + + spids := SortedPartyIDs{p1, p2} + + if !spids.Less(0, 1) { + t.Fatal("expected Less(0,1) = true for key 1 < key 2") + } + if spids.Less(1, 0) { + t.Fatal("expected Less(1,0) = false for key 2 > key 1") + } +} + +// TestSortPartyIDsDuplicateKeyPanics verifies that SortPartyIDs panics when +// two parties have the same key. +func TestSortPartyIDsDuplicateKeyPanics(t *testing.T) { + sameKey := big.NewInt(42) + p1 := NewPartyID("p1", "Party1", sameKey) + p2 := NewPartyID("p2", "Party2", sameKey) + + defer func() { + if r := recover(); r == nil { + t.Fatal("SortPartyIDs should panic on duplicate keys") + } + }() + SortPartyIDs(UnSortedPartyIDs{p1, p2}) +} + +// TestSortPartyIDsUniqueKeys verifies that SortPartyIDs succeeds with unique keys. +func TestSortPartyIDsUniqueKeys(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(3)) + p2 := NewPartyID("p2", "Party2", big.NewInt(1)) + p3 := NewPartyID("p3", "Party3", big.NewInt(2)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p1, p2, p3}) + + // Should be sorted by key: 1, 2, 3. + if sorted[0].KeyInt().Cmp(big.NewInt(1)) != 0 { + t.Fatalf("expected key 1 at index 0, got %s", sorted[0].KeyInt()) + } + if sorted[1].KeyInt().Cmp(big.NewInt(2)) != 0 { + t.Fatalf("expected key 2 at index 1, got %s", sorted[1].KeyInt()) + } + if sorted[2].KeyInt().Cmp(big.NewInt(3)) != 0 { + t.Fatalf("expected key 3 at index 2, got %s", sorted[2].KeyInt()) + } +} + +// TestSortPartyIDsEmptyInput verifies that SortPartyIDs handles empty and nil +// input without panicking and returns an empty slice. +func TestSortPartyIDsEmptyInput(t *testing.T) { + sorted := SortPartyIDs(UnSortedPartyIDs{}) + if len(sorted) != 0 { + t.Fatalf("expected empty slice, got length %d", len(sorted)) + } + + sorted = SortPartyIDs(nil) + if len(sorted) != 0 { + t.Fatalf("expected empty slice for nil input, got length %d", len(sorted)) + } +} + +// TestSortPartyIDsSingleParty verifies that a single party gets Index 0 after sorting. +func TestSortPartyIDsSingleParty(t *testing.T) { + p := NewPartyID("p1", "Party1", big.NewInt(99)) + sorted := SortPartyIDs(UnSortedPartyIDs{p}) + + if len(sorted) != 1 { + t.Fatalf("expected length 1, got %d", len(sorted)) + } + if sorted[0].Index != 0 { + t.Fatalf("expected Index 0, got %d", sorted[0].Index) + } +} + +// TestSortPartyIDsStartAt verifies that SortPartyIDs with a startAt parameter +// assigns indices starting at the given offset. +func TestSortPartyIDsStartAt(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(10)) + p2 := NewPartyID("p2", "Party2", big.NewInt(20)) + p3 := NewPartyID("p3", "Party3", big.NewInt(30)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p3, p1, p2}, 5) + + for i, pid := range sorted { + expected := i + 5 + if pid.Index != expected { + t.Fatalf("sorted[%d].Index = %d, want %d", i, pid.Index, expected) + } + } +} + +// TestSortPartyIDsIndexAssignment verifies that after sorting 5 parties, +// sorted[i].Index == i for all i. +func TestSortPartyIDsIndexAssignment(t *testing.T) { + ids := make(UnSortedPartyIDs, 5) + for i := 0; i < 5; i++ { + ids[i] = NewPartyID( + fmt.Sprintf("p%d", i), + fmt.Sprintf("Party%d", i), + big.NewInt(int64((i+1)*100)), + ) + } + + sorted := SortPartyIDs(ids) + + if len(sorted) != 5 { + t.Fatalf("expected length 5, got %d", len(sorted)) + } + for i, pid := range sorted { + if pid.Index != i { + t.Fatalf("sorted[%d].Index = %d, want %d", i, pid.Index, i) + } + } +} + +// TestSortPartyIDsAlreadySorted verifies that input already in ascending key +// order produces the same key order after sorting. +func TestSortPartyIDsAlreadySorted(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(1)) + p2 := NewPartyID("p2", "Party2", big.NewInt(2)) + p3 := NewPartyID("p3", "Party3", big.NewInt(3)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p1, p2, p3}) + + expectedKeys := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} + for i, pid := range sorted { + if pid.KeyInt().Cmp(expectedKeys[i]) != 0 { + t.Fatalf("sorted[%d] key = %s, want %s", i, pid.KeyInt(), expectedKeys[i]) + } + } +} + +// TestSortPartyIDsReverseSorted verifies that input in descending key order +// gets reversed after sorting. +func TestSortPartyIDsReverseSorted(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(30)) + p2 := NewPartyID("p2", "Party2", big.NewInt(20)) + p3 := NewPartyID("p3", "Party3", big.NewInt(10)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p1, p2, p3}) + + expectedKeys := []*big.Int{big.NewInt(10), big.NewInt(20), big.NewInt(30)} + for i, pid := range sorted { + if pid.KeyInt().Cmp(expectedKeys[i]) != 0 { + t.Fatalf("sorted[%d] key = %s, want %s", i, pid.KeyInt(), expectedKeys[i]) + } + } +} + +// TestPartyIDValidateBasicEmptyKey verifies ValidateBasic rejects empty keys. +// An empty key would produce KeyInt() == 0, breaking protocol invariants +// (e.g., duplicate detection, Lagrange interpolation). +func TestPartyIDValidateBasicEmptyKey(t *testing.T) { + pid := &PartyID{ + PartyIDData: &PartyIDData{Key: []byte{}}, + Index: 0, + } + result := pid.ValidateBasic() + if result { + t.Fatal("expected ValidateBasic() = false for empty Key") + } +} + +// TestPartyIDValidateBasicNilPid verifies that calling ValidateBasic on a nil +// *PartyID returns false. +func TestPartyIDValidateBasicNilPid(t *testing.T) { + var pid *PartyID + if pid.ValidateBasic() { + t.Fatal("expected ValidateBasic() = false for nil *PartyID") + } +} + +// TestPartyIDValidateBasicNegativeIndex verifies that a PartyID created via +// NewPartyID (which sets Index to -1) fails ValidateBasic. +func TestPartyIDValidateBasicNegativeIndex(t *testing.T) { + pid := NewPartyID("p1", "Party1", big.NewInt(42)) + if pid.Index != -1 { + t.Fatalf("expected NewPartyID to set Index = -1, got %d", pid.Index) + } + if pid.ValidateBasic() { + t.Fatal("expected ValidateBasic() = false for unsorted party with Index -1") + } +} + +// TestSortedPartyIDsFindByKey verifies that FindByKey returns the correct party +// for an existing key and nil for a missing key. +func TestSortedPartyIDsFindByKey(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(10)) + p2 := NewPartyID("p2", "Party2", big.NewInt(20)) + p3 := NewPartyID("p3", "Party3", big.NewInt(30)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p3, p1, p2}) + + // Find an existing key. + found := sorted.FindByKey(big.NewInt(20)) + if found == nil { + t.Fatal("expected to find party with key 20, got nil") + } + if found.KeyInt().Cmp(big.NewInt(20)) != 0 { + t.Fatalf("found party has key %s, want 20", found.KeyInt()) + } + + // Find a missing key. + missing := sorted.FindByKey(big.NewInt(999)) + if missing != nil { + t.Fatalf("expected nil for missing key, got %v", missing) + } +} + +// TestSortedPartyIDsExclude verifies that Exclude removes the specified party +// and the remaining count is correct. +func TestSortedPartyIDsExclude(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(10)) + p2 := NewPartyID("p2", "Party2", big.NewInt(20)) + p3 := NewPartyID("p3", "Party3", big.NewInt(30)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p1, p2, p3}) + + // Exclude the middle party (key 20). + remaining := sorted.Exclude(p2) + if len(remaining) != 2 { + t.Fatalf("expected 2 remaining parties, got %d", len(remaining)) + } + + // Verify that the excluded party is not present. + for _, pid := range remaining { + if pid.KeyInt().Cmp(big.NewInt(20)) == 0 { + t.Fatal("excluded party (key 20) should not be in remaining set") + } + } + + // Verify the remaining keys are correct. + expectedKeys := []*big.Int{big.NewInt(10), big.NewInt(30)} + for i, pid := range remaining { + if pid.KeyInt().Cmp(expectedKeys[i]) != 0 { + t.Fatalf("remaining[%d] key = %s, want %s", i, pid.KeyInt(), expectedKeys[i]) + } + } +} + +// TestSortedPartyIDsKeys verifies that Keys() returns the correct slice of +// *big.Int values in sorted order. +func TestSortedPartyIDsKeys(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(50)) + p2 := NewPartyID("p2", "Party2", big.NewInt(10)) + p3 := NewPartyID("p3", "Party3", big.NewInt(30)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p1, p2, p3}) + + keys := sorted.Keys() + if len(keys) != 3 { + t.Fatalf("expected 3 keys, got %d", len(keys)) + } + + expectedKeys := []*big.Int{big.NewInt(10), big.NewInt(30), big.NewInt(50)} + for i, k := range keys { + if k.Cmp(expectedKeys[i]) != 0 { + t.Fatalf("keys[%d] = %s, want %s", i, k, expectedKeys[i]) + } + } +} + +// TestGenerateTestPartyIDsStartAt verifies that GenerateTestPartyIDs with a +// startAt parameter assigns indices starting at the given offset. +func TestGenerateTestPartyIDsStartAt(t *testing.T) { + sorted := GenerateTestPartyIDs(3, 5) + if len(sorted) != 3 { + t.Fatalf("expected 3 parties, got %d", len(sorted)) + } + for i, pid := range sorted { + expected := i + 5 + if pid.Index != expected { + t.Fatalf("sorted[%d].Index = %d, want %d", i, pid.Index, expected) + } + } +} + +// TestGenerateTestPartyIDsDefaultStartAt verifies that GenerateTestPartyIDs +// without a startAt parameter assigns indices starting at 0. +func TestGenerateTestPartyIDsDefaultStartAt(t *testing.T) { + sorted := GenerateTestPartyIDs(4) + if len(sorted) != 4 { + t.Fatalf("expected 4 parties, got %d", len(sorted)) + } + for i, pid := range sorted { + if pid.Index != i { + t.Fatalf("sorted[%d].Index = %d, want %d", i, pid.Index, i) + } + } +} + +// TestGenerateTestPartyIDsUniqueKeys verifies that all generated parties have +// distinct keys. +func TestGenerateTestPartyIDsUniqueKeys(t *testing.T) { + sorted := GenerateTestPartyIDs(5) + seen := make(map[string]bool) + for _, pid := range sorted { + keyHex := pid.KeyInt().Text(16) + if seen[keyHex] { + t.Fatalf("duplicate key found: %s", keyHex) + } + seen[keyHex] = true + } +} + +// TestSortedPartyIDsToUnSorted verifies that ToUnSorted returns the same +// underlying parties (same keys and indices) as UnSortedPartyIDs. +func TestSortedPartyIDsToUnSorted(t *testing.T) { + p1 := NewPartyID("p1", "Party1", big.NewInt(10)) + p2 := NewPartyID("p2", "Party2", big.NewInt(20)) + p3 := NewPartyID("p3", "Party3", big.NewInt(30)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p3, p1, p2}) + unsorted := sorted.ToUnSorted() + + if len(unsorted) != len(sorted) { + t.Fatalf("expected %d parties, got %d", len(sorted), len(unsorted)) + } + + // Same pointers, same order. + for i := range sorted { + if sorted[i] != unsorted[i] { + t.Fatalf("sorted[%d] and unsorted[%d] point to different PartyIDs", i, i) + } + } +} + +// TestNewPartyIDZeroKey verifies that NewPartyID with big.NewInt(0) sets +// Key to []byte{} (empty, since big.Int(0).Bytes() returns empty). +// This is important for cross-language compatibility. +func TestNewPartyIDZeroKey(t *testing.T) { + pid := NewPartyID("p0", "Party0", big.NewInt(0)) + + // big.NewInt(0).Bytes() = []byte{} (empty). + if len(pid.Key) != 0 { + t.Fatalf("expected empty Key for big.NewInt(0), got %v", pid.Key) + } + + // KeyInt() should still reconstruct to 0. + if pid.KeyInt().Cmp(big.NewInt(0)) != 0 { + t.Fatalf("KeyInt() = %s, want 0", pid.KeyInt()) + } + + // Index should be -1 (unsorted). + if pid.Index != -1 { + t.Fatalf("expected Index -1, got %d", pid.Index) + } +} + +// TestPartyIDStringFormat verifies the String() format: "{Index,Moniker}". +func TestPartyIDStringFormat(t *testing.T) { + pid := NewPartyID("p1", "Alice", big.NewInt(42)) + // Before sorting, Index is -1. + expected := "{-1,Alice}" + got := pid.String() + if got != expected { + t.Fatalf("String() = %q, want %q", got, expected) + } + + // After sorting, Index becomes 0. + sorted := SortPartyIDs(UnSortedPartyIDs{pid}) + expected = fmt.Sprintf("{0,%s}", "Alice") + got = sorted[0].String() + if got != expected { + t.Fatalf("String() after sort = %q, want %q", got, expected) + } +} + +// TestSSIDNonceUintType verifies that SSIDNonce is uint, preventing the +// sign collision where big.Int.Bytes() drops the sign (so -N and N would +// produce identical SSID inputs if int were allowed). +func TestSSIDNonceUintType(t *testing.T) { + // Verify that distinct nonces produce different byte representations. + zero := new(big.Int).SetUint64(0).Bytes() + one := new(big.Int).SetUint64(1).Bytes() + if string(zero) == string(one) { + t.Fatal("nonce 0 and 1 should produce different bytes") + } + + // SetSSIDNonce now takes uint, preventing negative values at compile time. + pIDs := GenerateTestPartyIDs(2) + p2pCtx := NewPeerContext(pIDs) + params := NewParameters(S256(), p2pCtx, pIDs[0], 2, 1) + params.SetSSIDNonce(1) + if params.SSIDNonce() != 1 { + t.Fatalf("SSIDNonce should be 1, got %d", params.SSIDNonce()) + } + + // Verify large uint values work correctly. + params.SetSSIDNonce(^uint(0)) // max uint + if params.SSIDNonce() != ^uint(0) { + t.Fatalf("SSIDNonce should be max uint, got %d", params.SSIDNonce()) + } +} + +// TestPartyIDStringFormatMultiParty verifies String() format for multiple parties. +func TestPartyIDStringFormatMultiParty(t *testing.T) { + p1 := NewPartyID("p1", "Alice", big.NewInt(10)) + p2 := NewPartyID("p2", "Bob", big.NewInt(20)) + p3 := NewPartyID("p3", "Charlie", big.NewInt(30)) + + sorted := SortPartyIDs(UnSortedPartyIDs{p3, p1, p2}) + + // After sorting: Alice(10) at 0, Bob(20) at 1, Charlie(30) at 2. + tests := []struct { + index int + expected string + }{ + {0, "{0,Alice}"}, + {1, "{1,Bob}"}, + {2, "{2,Charlie}"}, + } + for _, tc := range tests { + got := sorted[tc.index].String() + if got != tc.expected { + t.Fatalf("sorted[%d].String() = %q, want %q", tc.index, got, tc.expected) + } + } +} diff --git a/tss-lib/tss/peers.go b/tss-lib/tss/peers.go index c94068f..803ab66 100644 --- a/tss-lib/tss/peers.go +++ b/tss-lib/tss/peers.go @@ -1,8 +1,7 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. +// Copyright (c) 2019 Binance +// Copyright (c) 2026 Hemi Labs, Inc. +// Use of this source code is governed by the MIT License, +// which can be found in the LICENSE file. package tss @@ -12,14 +11,17 @@ type ( } ) +// NewPeerContext creates a peer context from sorted party IDs. func NewPeerContext(parties SortedPartyIDs) *PeerContext { return &PeerContext{partyIDs: parties} } +// IDs returns the sorted party IDs in this peer context. func (p2pCtx *PeerContext) IDs() SortedPartyIDs { return p2pCtx.partyIDs } +// SetIDs replaces the party IDs in this peer context. func (p2pCtx *PeerContext) SetIDs(ids SortedPartyIDs) { p2pCtx.partyIDs = ids } diff --git a/tss-lib/tss/round.go b/tss-lib/tss/round.go deleted file mode 100644 index ab24218..0000000 --- a/tss-lib/tss/round.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package tss - -type Round interface { - Params() *Parameters - Start() *Error - Update() (bool, *Error) - RoundNumber() int - CanAccept(msg ParsedMessage) bool - CanProceed() bool - NextRound() Round - WaitingFor() []*PartyID - WrapError(err error, culprits ...*PartyID) *Error -} diff --git a/tss-lib/tss/wire.go b/tss-lib/tss/wire.go deleted file mode 100644 index bc24df5..0000000 --- a/tss-lib/tss/wire.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright © 2019 Binance -// -// This file is part of Binance. The full Binance copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -package tss - -import ( - "errors" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" -) - -// Used externally to update a LocalParty with a valid ParsedMessage -func ParseWireMessage(wireBytes []byte, from *PartyID, isBroadcast bool) (ParsedMessage, error) { - wire := new(MessageWrapper) - wire.Message = new(anypb.Any) - wire.From = from.MessageWrapper_PartyID - wire.IsBroadcast = isBroadcast - if err := proto.Unmarshal(wireBytes, wire.Message); err != nil { - return nil, err - } - return parseWrappedMessage(wire, from) -} - -func parseWrappedMessage(wire *MessageWrapper, from *PartyID) (ParsedMessage, error) { - m, err := wire.Message.UnmarshalNew() - if err != nil { - return nil, err - } - meta := MessageRouting{ - From: from, - IsBroadcast: wire.IsBroadcast, - } - if content, ok := m.(MessageContent); ok { - return NewMessage(meta, content, wire), nil - } - return nil, errors.New("ParseWireMessage: the message contained unknown content") -}