Shigoto-dev19 / ec-elgamal-circom

ElGamal encryption/decryption Circom2 circuits on the Baby Jubjub curve with TypeScript integration for input handling, testing, and benchmarking.
4 stars 1 forks source link

Comparison to your classic elgamal repository #8

Open numtel opened 7 months ago

numtel commented 7 months ago

Hello, I'm new to writing Circom circuits and was wondering about the security status of this repository versus the classic elgamal implementation repository.

As far as I can tell, both repos use 254 bit private keys so it seems like the warning about intentional insecurity should also apply to this code.

Is this correct? If so, is there a way to encrypt/decrypt using a larger 2048 bit key?

Thanks

Shigoto-dev19 commented 6 months ago

That's a fair point @numtel, and that's the reason that motivated me to try to do the classic ElGamal implementation on Circom.

numtel commented 6 months ago

Thanks for the response. This is definitely at the limit of my mathematical understanding but I've read through this linked notion page. Pollard's rho seems like the biggest potential vulnerability? Seeing the potential attacks listed was very helpful because in my calculations, a brute force attack was infeasible. Of course, circom limits the key size to the field element size but I think I was wondering if it were possible to split a longer key into multiple encryptions if necessary. Although the ciphertext doubles the plaintext length with each encryption, it seems possible albeit cumbersome.

Some backstory about my application: At the Bogota 2022 hackathon, I was on the Ethereum Social Contract team. After what had gone down with OFAC and Tornado Cash, we wanted to make a legally-compliant mixer (by allowing a single very private key [like as secret as the ICANN DNS key] access to decrypt transactions) but I had no clue at the time how to implement it.

We need a method of proving that a ciphertext corresponds to a particular plaintext value encrypted by a specific key. At this time, I see using the encode/encrypt circuits from this repo added to a fork of Semaphore v4 that also outputs the ciphertext and public key as part of its circuit's public signals.

I've started trying to implement this but I'm running into the issue of the encoding done in javascript not matching the encoding done by the circuit, since I'll be encoding the identityCommitment as the plaintext value. I don't know if I'm doing something wrong or if there is something missing here.

See this failing test: https://github.com/Shigoto-dev19/ec-elgamal-circom/commit/2a5156f13a58417b7f7a42729b892af1fd5fb980 I noticed that I was comparing the wrong values. It should be:

            expect(prove_encode.publicSignals[0]).to.equal(encoded.x.toString());
            expect(prove_encode.publicSignals[1]).to.equal(encoded.y.toString());

:crossed_fingers: Nice, ok continuing on semaphore fork...

From your response, I gather that this repo is more secure than the classic version because of the EC used. As a result of this though, it limits the plaintext input to 32 bits. I think 32 bits of the identityCommitment would be enough for an MVP.

Again, thanks so much for this work

Shigoto-dev19 commented 6 months ago

@numtel I am glad that my work is helpful to a fellow enthusiast.

I hope my work will be of more help to you and others :)