We do not do parties, we do multi-parties! One of the most important ingredients for these is (next to mate) oblivious transfers.
Time
3 hours
Solved 1 hour after the ctf end :(
Behavior
The server use paillier cryptosystem, we can provide generator c and publickey n, then the server computes a encrypted flag using following formula. x0x1r0,r1c0c1=rand(sizeof(flag))=x0flag=rand(n),rand(n)=(enc(1)×c(n−1))x0×cr0=(enc(1)×c(n−1))r1×cx1 and returns ciphertext c0,c1 to us.
Solution
TL;DR
- Generate a safe prime q=2p+1
- Use n=pq as public key
- Send enc(q) as c
- x0=dec(c0) mod p
- x1=dec(c1) mod q
In paillier, multiplication in ciphertext is addition in plaintext, and power in ciphertext is multiplication in plaintext. So the decryption result will be: cd0d1:=enc(z)=x0−z(x0−r0) mod n=r1−z(r1−x1) mod n
To solve this task, I use a safe prime as c and private key, formally: qnc:=2p+1where p, q are both prime:=pq:=enc(q) After decryption, we'll have: d0d1=x0−q(x0−r0) mod pq=r1−q(r1−x1) mod pq To get x0, simply calculate the remainder over q: d0=x0−q(x0−r0)=x0 mod q
x1 is more complicated. Recall that q=2p+1, we can derive following formulas: r1d1:=pk+(r1mod p)=r1−q(r1−x1) mod pq=r1−q(pk+(r1mod p)−x1) mod pq=r1−pqk−q((r1mod p)−x1) mod pq=r1−q((r1mod p)−x1) mod pq=r1−(2p+1)((r1mod p)−x1) mod pq: {Under modulo p}=r1−(2p+1)((r1mod p)−x1) mod p=r1−1((r1mod p)−x1) mod p=r1−(r1mod p)+x1 mod p=x1 mod p
Now xor those two integer to get the flag.
Additional Notes
Here's the solution from admin. It is stronger than my solution which doesn't need the assumption of safe prime on private key. Here's a proof about how it works:
Using extended gcd to get X, Y, such that: pX+qY=gcd(p,q)=1
Using the equation above, we have following equation about multiplicative inverse: ⇒ ⇒ pX1×pX=1=pX+qYpX1=pXpX+qY=1+pXqYqY1×qY=1=pX+qYqY1=qYpX+qY=1+qYpX
Select c=enc(α), where α=pXmodpq
So that: d0=dec(c0)=x0−α(x0−r0)modpq=x0−pX(x0−r0)modpq: {under modulo p}=x0−pX(x0−r0)modp=x0modp
However the script calculate x0 using: x0:=qYd0modp which is also true.
qYd0=qYx0modp=x0(1+qYpX)modp=x0modp
We can calculate x1 from d1 in the similar way: d1pXd1=dec(c1)=r1−α(r1−x1)modpq=r1−pX(r1−x1)modpq=pXr1−r1+x1modpq=r1(1+pXqY)−r1+x1modpq: {under modulo q}=r1(1+pXqY)−r1+x1modq=r1−r1+x1modq=x1modq