Skip to content

Commit

Permalink
performance optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
Janis Erdmanis committed Nov 3, 2024
1 parent 2d19495 commit 00cf184
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 22 deletions.
8 changes: 4 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ShuffleProofs"
uuid = "31a120cc-b3cb-4d07-bbdb-d498660ddfd8"
authors = ["Janis Erdmanis <[email protected]>"]
version = "0.4.1"
version = "0.4.2"

[deps]
CryptoGroups = "bc997328-bedd-407e-bcd3-5758e064a52d"
Expand All @@ -11,10 +11,10 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SigmaProofs = "f8559b4c-f045-44a2-8db2-503e40bb7416"

[compat]
CryptoGroups = "0.5"
CryptoPRG = "0.1"
CryptoGroups = "0.6"
CryptoPRG = "0.2"
CryptoUtils = "0.1.1"
SigmaProofs = "0.1"
SigmaProofs = "0.2"
julia = "1"

[extras]
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Unlike traditional cryptographic tools that focus solely on confidentiality and
- **Cryptographic Infrastructure**
- Extensible group support for arbitrary cyclic groups
- Native elliptic curves over prime fields (P-192, P-256, secp256k1)
- High-performance OpenSSL curve integration via [OpenSSLGroups.jl](https://github.com/PeaceFounder/OpenSSLGroups.jl)
- Optional high-performance OpenSSL curve integration via [OpenSSLGroups.jl](https://github.com/PeaceFounder/OpenSSLGroups.jl)
- Modular prime groups with flexible parameter selection
- Secure hash based random number generation for proof components via [CryptoPRG.jl](https://github.com/PeaceFounder/CryptoPRG.jl)
- Flexible verifier interface for custom implementations
Expand Down Expand Up @@ -196,7 +196,11 @@ simulator = shuffle(ciphertexts, g, pk, verifier)
@assert verify(simulator)
```

Early benchmarks suggest that with OpenSSL `Prime256v1` implementation `verify` is **30x faster** compared to the `CryptoGroups` implementation. Half of the time is spent computing Jacoby symbol for `generator_basis` and one third of the time is spent into `Parser` module which can be improved in the future to increase performance for another 5x.
Early benchmarks suggest that with OpenSSL `Prime256v1` implementation, verification is about **25 times faster** than with `CryptoGroups` curve implementation.

![](test/benchmarks/VerifierProfile.png)

Performance profiling reveals three major computational bottlenecks in the code: generator basis computation via `generator_basis` consumes 40% of execution time (left), verification of proof through group operations takes another 40% (right), and challenge generation via `challenge_perm` and `challenge_reenc` accounts for the remaining 20% (middle). While the generator basis computation and proof verification stages can be readily parallelised using either multithreading or multiprocessing, the challenge generation stage presents parallelisation roadblocks. Within this challenge generation phase, approximately 1/3rd of processing time is spent computing hashes from byte vectors using Nettle (highlighted in the profile view with yellow pencil fill). Hence, the specification would need to introduce block-wise hashing to parallelise this part.

## References

Expand Down
34 changes: 23 additions & 11 deletions src/verifier.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using SigmaProofs.Verificatum: generator_basis, ProtocolSpec, ro_prefix
using CryptoPRG.Verificatum: HashSpec, PRG, RO, ROPRG
using CryptoGroups: Group, PGroup, ECGroup
using SigmaProofs.ElGamal: width
using SigmaProofs.Parser: Tree, Leaf, interpret, encode
using SigmaProofs.Parser: Tree, Leaf, interpret, encode, encode!


struct VShuffleProof{G<:Group, N} <: Proof
Expand Down Expand Up @@ -105,7 +105,12 @@ function seed(spec, proposition, 𝐮;

tree = Tree((g, 𝐡, 𝐮, pk_tree, 𝔀, 𝔀′))

prg = roprg(encode(tree))
# We may need a reliable way for getting buffer size here
buffer = IOBuffer(; sizehint=1000000)
encode!(buffer, tree)
bytes = take!(buffer)

prg = roprg(bytes)

(; s) = prg

Expand Down Expand Up @@ -145,20 +150,28 @@ end


function challenge_reenc(spec::ProtocolSpec{G}, proposition::Shuffle{G}, 𝐮, τ::Tuple{Vector{G}, G, Vector{G}, G, G, ElGamalRow{G, N}};
ρ = ro_prefix(spec),
s = seed(spec, proposition, 𝐮; ρ)
) where {G <: Group, N}

ρ = ro_prefix(spec),
s = seed(spec, proposition, 𝐮; ρ)
) where {G <: Group, N}
(; nv, rohash) = spec

ro_challenge = RO(rohash, nv)

# Create an IOBuffer to build the challenge input incrementally
io = IOBuffer()

# Write prefix bytes
write(io, ρ)

# Write tree directly to buffer without intermediate allocation
tree_challenge = Tree((Leaf(s), τ))
𝓿 = interpret(BigInt, ro_challenge([ρ..., encode(tree_challenge)...]))

encode!(io, tree_challenge)

# Get final bytes and compute challenge
challenge_bytes = take!(io)
𝓿 = interpret(BigInt, ro_challenge(challenge_bytes))
return 𝓿
end


function challenge_reenc(spec::ProtocolSpec{G}, proposition::Shuffle{G}, 𝐜, 𝐜̂::Vector{G}, t::Tuple{G, G, G, ElGamalRow{G, N}, Vector{G}};
ρ = ro_prefix(spec),
s = seed(spec, proposition, 𝐜; ρ)
Expand All @@ -178,7 +191,6 @@ function challenge_reenc(spec::ProtocolSpec{G}, proposition::Shuffle{G}, 𝐜,
return challenge_reenc(spec, proposition, 𝐜, τ; ρ, s)
end


function verify(proposition::Shuffle, proof::VShuffleProof, challenge::PoSChallenge; verbose=false)

𝐡, 𝐞, 𝓿 = challenge.𝐡, challenge.𝐮, challenge.c
Expand Down
Binary file added test/benchmarks/VerifierProfile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 9 additions & 5 deletions test/openssl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,21 @@ openssl_braid_simulator = load(Simulator{Braid{typeof(g)}}, BRAID_DIR)

### Testing proof loading

simulator = load_verificatum_simulator("$(@__DIR__)/validation_sample/verificatum/P256/"; G = @ECGroup{OpenSSLGroups.Prime256v1})
BASE_DIR = "$(@__DIR__)/validation_sample/verificatum/P256/"

@btime simulator = load_verificatum_simulator(BASE_DIR; G = @ECGroup{OpenSSLGroups.Prime256v1})

#@btime simulator = load_verificatum_simulator("$(@__DIR__)/validation_sample/verificatum/P256/"; G = @ECGroup{OpenSSLGroups.Prime256v1})
@test verify(simulator)

# Only about 8 times faster than CryptoGroups implementation here.
#simulator_ord = load_verificatum_simulator("$(@__DIR__)/validation_sample/verificatum/P256/")
# About 25 times faster than CryptoGroups implementation here.
@btime simulator_ord = load_verificatum_simulator("$(@__DIR__)/validation_sample/verificatum/P256/")
#@btime verify(simulator_ord)
#@btime verify(simulator)

### For extended width

simulator = load_verificatum_simulator("$(@__DIR__)/validation_sample/verificatum/P192w3/"; G = @ECGroup{OpenSSLGroups.Prime192v1})
@test verify(simulator) # only about 5 times faster
# simulator = load_verificatum_simulator("$(@__DIR__)/validation_sample/verificatum/P192w3/"; G = @ECGroup{OpenSSLGroups.Prime192v1})
# @test verify(simulator) # only about 5 times faster


2 comments on commit 00cf184

@JanisErdmanis
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/118596

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.4.2 -m "<description of version>" 00cf1848aef9d2be45a7f45fd6e739ce32d448a9
git push origin v0.4.2

Please sign in to comment.