-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Janis Erdmanis
committed
Oct 11, 2024
1 parent
3c20b98
commit 346e9b5
Showing
32 changed files
with
3,390 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Workflow for Codecov example-julia | ||
on: [push, pull_request] | ||
jobs: | ||
run: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Set up Julia 1.10.0 | ||
uses: julia-actions/setup-julia@v1 | ||
with: | ||
version: "1.10.0" | ||
- uses: julia-actions/julia-buildpkg@v1 | ||
- uses: julia-actions/julia-runtest@v1 | ||
- uses: julia-actions/julia-processcoverage@v1 | ||
- uses: codecov/codecov-action@v4 | ||
env: | ||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: TagBot | ||
on: | ||
issue_comment: | ||
types: | ||
- created | ||
workflow_dispatch: | ||
inputs: | ||
lookback: | ||
default: 3 | ||
permissions: | ||
contents: write | ||
jobs: | ||
TagBot: | ||
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: JuliaRegistries/TagBot@v1 | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
ssh: ${{ secrets.DOCUMENTER_KEY }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
**/*~ | ||
**/*.bak | ||
**/\#*\# | ||
**/.DS_Store | ||
Manifest.toml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name = "SigmaProofs" | ||
uuid = "f8559b4c-f045-44a2-8db2-503e40bb7416" | ||
authors = ["Janis Erdmanis <janiserdmanis@protonmail.ch>"] | ||
version = "0.1.0" | ||
|
||
[deps] | ||
CryptoGroups = "bc997328-bedd-407e-bcd3-5758e064a52d" | ||
CryptoPRG = "d846c407-34c1-46cb-aa27-d51818cc05e2" | ||
CryptoUtils = "04afed74-ac16-11e9-37b6-1352e3e05830" | ||
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" | ||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" | ||
|
||
[compat] | ||
CryptoGroups = "0.5.0" | ||
CryptoPRG = "0.1.1" | ||
CryptoUtils = "0.1.1" | ||
InteractiveUtils = "1.11.0" | ||
Random = "1.11.0" | ||
Test = "1.11.0" | ||
|
||
[extras] | ||
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" | ||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" | ||
|
||
[targets] | ||
test = ["Test", "SafeTestsets"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# TODO: RANGE PROOFS ARE NOT YET IMPLEMENTED | ||
|
||
# Auctions: [AW13] uses range proofs for verifiable auctions. Range proofs help an auctioneer to prove to an auditor that the sale price was set correctly without revealing the values of the bids. For example, in a second-price auction with | ||
# n n bids, (where the sale price is equal to the second-highest bid), the auctioneer can provide proofs that n 1−1 bids were at most the sale price and one bid was greater than the sale price | ||
|
||
|
||
# The setup is that the Dealer registers participant public keys which are used to sign auction bids (which we shall skip). The bids themselves are ElGamal encrypted under an authorithy issued public key. | ||
|
||
# (1) Keygen of authorithy, providing pk | ||
# (3) Bidders make a bids encrypted in ElGamal texts. Additionally proof of knowledge for the exponent can be provided if the bidding is made public | ||
# (4) Authorithy selects highest bidder and decrypts the second highest bid and provides decryption ZKP | ||
# (5) Now for every single bid the authorithy makes a range proof proving that it's value is lower than that of the winning bid. Before we can do so the authorithy needs to reencrypt ElGamal cyphertexts with their own exponent which it can prove to encrypt the same plaintext with plaintext equivalence test Dec((a, b)/(a', b')) = 1. Then one can proceed with NRange proofs as desired. | ||
|
||
|
||
sk, pk = keygen(g) | ||
𝐺 = basis_generators[1] | ||
|
||
function bid(value) | ||
|
||
α = rand(2:order(G)-1) | ||
|
||
a = g^α | ||
b = pk^α * 𝐺^value | ||
|
||
return (a, b) | ||
end | ||
|
||
|
||
function dec((a, b)) | ||
|
||
m = b / a^sk | ||
|
||
isone(m) && return 0 | ||
|
||
for i in 1:30 | ||
𝐺^i == m && return i | ||
end | ||
|
||
error("Value not in range") # In practice thoose are decrypted as a proof | ||
end | ||
|
||
|
||
# Made bids by third parties. In real situation they are signed. May also require knowledge proof of exponenent to avoid Pfitzman attack, but it is unpractical to execute it as only the winners value is decrypted. | ||
|
||
v_A = 10 | ||
bid_A = bid(v_A) | ||
|
||
v_B = 20 | ||
bid_B = bid(v_B) | ||
|
||
v_C = 15 | ||
bid_C = bid(v_C) | ||
|
||
# The dealer decrypts every bid privatelly: | ||
|
||
@test dec(bid_A) == v_A | ||
@test dec(bid_B) == v_B | ||
@test dec(bid_C) == v_C | ||
|
||
# It sees that bid_B is the highest and hence had won. It needs to pay second largest bid bid_C. Now it needs to prove that it had acted honestly which can be done with range proofs. Before such proofs can be executed we need to make a substitutes. | ||
|
||
α_A = rand(2:order(G)-1) | ||
substitute_A = substitute(g, pk, bid_A..., sk, α_A, verifier) | ||
|
||
α_B = rand(2:order(G)-1) | ||
substitute_B = substitute(g, pk, bid_B..., sk, α_B, verifier) | ||
|
||
decryption_C = decrypt(g, bid_C, sk, verifer) | ||
|
||
C_C = 𝐺^v_C # α = 0 | ||
range_BC = rangecommit(4, g, pk, v_B - v_C, verifier; α = α_B) | ||
range_CA = rangecommit(4, g, pk, v_C - v_A, verifier; α = -α_A) | ||
|
||
### The auditor then can do the audit as follows | ||
|
||
v_C = dec(decryption_C) | ||
C_C = 𝐺^v_C | ||
C_A = substitute_A.b′ | ||
C_B = substitute_B.b′ | ||
|
||
@test range_A.proposition.y == C_B / C_C | ||
@test range_A.proposition.y == C_C / C_A | ||
|
||
@test verify(substitute_A) | ||
@test verify(substitute_B) | ||
@test verify(decryption_C) | ||
|
||
@test verify(range_BC) | ||
@test verify(range_CA) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
module CommitmentShuffle | ||
|
||
using CryptoGroups | ||
using ..SigmaProofs: Proposition, Proof, Verifier, Simulator, challenge, generator_basis, gen_roprg | ||
using ..SigmaProofs.LogProofs: SchnorrProof, LogKnowledge | ||
import ..SigmaProofs: prove, verify, proof_type | ||
|
||
# This document lays out a draft protocol that is designed to achieve information-theoretic security for a shuffle. The goal is to ensure long-lasting privacy if cryptogrpahically relevant quantum computer ever gets built in the future (which is unlikelly). The protocol requires interaction from the secret owners and hence it can not be used in cascade in a simple way, but it's outputs can be passed further down the line in ordinary ElGamal reencryption shuffle methods as implemented in ShuffleProofs. The everlating privacy in this way ends up being ensured by one authorithy which in if corrupt in the presence of quantum computer could link individual voters to votes and hence significatnly reduces the risk as there is no near term incentives for a corrupt authorithy to keep this data. | ||
|
||
# Note that this is a preliminary draft, and the protocol may not be sound and have already been revised multiple times because of that. There’s also possibility that similar protocols may already exist in published literature which would be good to know. | ||
|
||
# Goal: This protocol creates a system where each member gets a new, unlinkable public key, while allowing for public verification | ||
# that each member received exactly one key, without revealing which key belongs to which member. | ||
|
||
# 1. Setup: | ||
# - A verifiable generator list is established | ||
# - A blinding generator 'h' is set | ||
|
||
# 2. Dealer-member interaction: | ||
# - Dealer sends a verifiably random generator g_i to each member | ||
# - Member generates x_i and β_i | ||
# - Member computes: | ||
# * u_i <- g_i^x | ||
# * C = h^β * u_i | ||
# * PoK{(x): u_i = g_i^x_i) | ||
# - Member sends back to dealer: | ||
# * Signed {C} | ||
# * β_i | ||
# * u_i | ||
# * PoK{(x): u_i <- g_i^x_i) | ||
# - Dealer publishes the commitment on a public bulletin board | ||
|
||
# 3. Dealer's consistency proof: | ||
# - Dealer generates a secret vector r_i | ||
# - Computes A <- h^r * ∏ u_i^s_i | ||
# - Computes e_i from anouncement A using Fiat-Shamir transform | ||
# - Computes secrets: | ||
# * z = r + \sum_i \beta_i * e_i | ||
# * w_i = s_i + e_i | ||
# - Announces on public bulletin board: | ||
# * Shuffled list of (u_i, g_i, PoK{(x_i): u_i = g_i^x_i}, w_i) and anouncement A, z | ||
|
||
# 4. Verification process: | ||
# - Verify that every g_i was generated verifiably random | ||
# - Verify PoK for every generator used in the commitment proof PoK{(x): u_i = g_i^x_i} | ||
# - Compute e_i from A | ||
# - Check that h^z * ∏ u_i^(s_i) = A * ∏ C_i^e_i | ||
|
||
# This protocol aims to ensure everlasting privacy in a braiding scheme by using generalized Pedersen commitments and zero-knowledge proofs. It allows members to participate individually with a dealer over a confidential quantum-resistant channel, addressing the potential threat of future quantum computers breaking the privacy of current cryptographic schemes. | ||
|
||
# For convenience, in the case of braiding, this can be part of the registration protocol. Each member generates a list of key commitments by selecting verifiable generators at random locally, as well as the blinding factors. They then deliver the membership certificate that lists commitments along with the secrets via a quantum-resistant channel. The coresponding authetification can be performed via ordinary public key cryptography as currently there is no cryptographically relevant quantum computer that could compromise that and it does not help adversary in the future to break ever lasting privacy. | ||
|
||
# WARNING: THIS PROTOCOL IS CREATION OF MY OWN AND HAS NOT BEEN CHECKED RIGOROUSLY THAT IT IS BINDING | ||
|
||
struct CommittedRow{G <: Group, T} | ||
g::G | ||
u::G | ||
m::T # Can be arbitrary type. A single group element, or ElGamalRow that can be passed further down to a mix cascade. | ||
pok::SchnorrProof{G} | ||
end | ||
|
||
Base.isless(x::T, y::T) where T <: CommittedRow = isless(x.u, y.u) | ||
|
||
function verify(row::CommittedRow, verifier::Verifier) | ||
|
||
(; m, g, u, pok) = row | ||
proposition = LogKnowledge(g, u) | ||
|
||
return verify(proposition, pok, verifier; suffix = m) | ||
end | ||
|
||
# perhaps naming it as dercom, derive_commit | ||
function commit(m::G, g::G, h::G, verifier::Verifier; roprg = gen_roprg(), x = rand(roprg(:x), 2:order(G)-1)) where G <: Group | ||
|
||
u = g^x | ||
β = rand(roprg(:β), 2:order(G)-1) | ||
|
||
C = h^β * u | ||
|
||
pok = prove(LogKnowledge(g, u), verifier, x; suffix = m) | ||
|
||
row = CommittedRow(g, u, m, pok) | ||
|
||
return row, C, β | ||
end | ||
|
||
isbinding(row::CommittedRow{G}, C::G, h::G, β::Integer) where G <: Group = h^β * row.u == C | ||
|
||
struct Shuffle{G<:Group} <: Proposition # What is shown on public buletin board | ||
h::G | ||
𝐂::Vector{G} # need to be individually signed | ||
rows::Vector{<:CommittedRow{G}} | ||
end | ||
|
||
Base.length(proposition::Shuffle) = length(proposition.𝐂) | ||
|
||
struct ShuffleProof{G<:Group} <: Proof | ||
A::G | ||
z::BigInt | ||
𝐰::Vector{BigInt} | ||
end | ||
|
||
proof_type(::Type{Shuffle{G}}) where G <: Group = ShuffleProof{G} | ||
|
||
function verify(proposition::Shuffle{G}, proof::ShuffleProof{G}, verifier::Verifier; nmax = 10 * length(proposition)) where G <: Group | ||
|
||
(; h, 𝐂, rows) = proposition | ||
(; A, z, 𝐰) = proof | ||
|
||
𝐠 = (i.g for i in rows) | ||
|
||
basis = generator_basis(verifier, G, nmax) | ||
|
||
h in 𝐠 && return false # blinding factor can't be one of the generators | ||
length(unique(𝐠)) == length(𝐠) || return false # every generator must be unique | ||
|
||
all(x -> x.g in basis, rows) || return false # generator not in basis | ||
|
||
all(x -> verify(x, verifier), rows) || return false # pok for committed value exponent | ||
|
||
# Now we have established that 𝐮 forms an independet generator basis set | ||
|
||
𝐞 = challenge(verifier, proposition, A) | ||
𝐮 = (x.u for x in rows) | ||
h^z * prod(𝐮 .^ 𝐰) == A * prod(𝐂 .^ 𝐞) || return false | ||
|
||
# Hence the vector (𝐠, 𝐮) is consistent with commitment vector 𝐂 | ||
|
||
return true | ||
end | ||
|
||
|
||
# The blinding factors are for commitment order | ||
# the proofs pok can be oermuted sepereatelly in place | ||
|
||
function prove(proposition::Shuffle{G}, verifier::Verifier, 𝛃::Vector{<:Integer}, 𝛙::Vector{<:Integer}; roprg = gen_roprg()) where G | ||
|
||
(; h, rows, 𝐂) = proposition | ||
𝐮 = (x.u for x in rows) | ||
|
||
𝐬 = rand(roprg(:𝐬), 2:order(G) - 1, length(𝛃)) | ||
r = rand(roprg(:r), 2:order(G) - 1) | ||
|
||
A = h^r * prod(𝐮 .^ 𝐬) | ||
|
||
𝐞 = challenge(verifier, proposition, A) | ||
|
||
z = r + sum(𝛃 .* 𝐞) | ||
𝐰 = 𝐬 .+ view(𝐞, 𝛙) | ||
|
||
return ShuffleProof(A, z, 𝐰) | ||
end | ||
|
||
|
||
function shuffle(rows::Vector{<:CommittedRow{G}}, h::G, 𝐂::Vector{G}, 𝛃::Vector{<:Integer}, verifier::Verifier; 𝛙 = sortperm(rows)) where G <: Group | ||
|
||
proposition = Shuffle(h, 𝐂, rows[𝛙]) | ||
proof = prove(proposition, verifier, 𝛃, 𝛙) | ||
|
||
return Simulator(proposition, proof, verifier) | ||
end | ||
|
||
|
||
end |
Oops, something went wrong.