Skip to content

Commit 3693ea1

Browse files
committed
Improved beginning of elgamal tutorial
1 parent 0deff6b commit 3693ea1

1 file changed

Lines changed: 69 additions & 13 deletions

File tree

getting-started/implement-elgamal.md

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,84 @@ tpc: true
55
---
66

77
In this document, we show to to use the Cryptimeleon Craco and Cryptimeleon Math library to implement an example scheme, the Elgamal encryption scheme [Elg85].
8-
Compared to the other tutorials, we also aim to showcase a possible class structure that could be used as well as introduce the library's intermediate serialization framework to you along the way.
8+
Compared to the other tutorials, we also aim to showcase the class structure for a full implementatio (as opposed to "just" a toy implementation).
99

10-
First, lets review how ElGamal encryption works:
10+
First, let's review how ElGamal encryption works:
1111

1212
Let \\(G\\) be a cyclic group of prime order \\(q\\).
1313

14-
**\\(\operatorname{KeyGen}\\)**:
14+
**\\(\\operatorname{Setup}\\)**:
15+
The public parameters for this scheme consist of (1) a cyclic group \\(G\\) of prime order \\(p\\), and (2) a random generator \\(g\\leftarrow G\\setminus\\{1\\}\\).
1516

16-
1. Choose integer \\(a\\) from \\(\\{0, 1, \dots, q-1\\}\\) uniformly at random.
17-
2. Choose generator \\(g \\leftarrow G\\) uniformly at random.
18-
3. The secret key is \\(sk = (G, g, a, h=g^a)\\) and the public key is \\(pk = (G, g, h)\\).
17+
**\\(\\operatorname{KeyGen}\\)**:
1918

20-
**\\(\operatorname{Encryption}(pk, m)\\)**:
19+
1. Choose a random secret key \\(sk \\leftarrow \\{0, 1, \dots, p-1\\}\\).
20+
2. Compute the corresponding public key \\(pk = g^{sk}\\)
2121

22-
1. Choose \\(r\\) from \\(\\{0, 1, \dots, q-1\\}\\) uniformly at random.
23-
2. The ciphertext is \\(c = (c_1, c_2) = (g^r, m \cdot h^r)\\).
22+
**\\(\\operatorname{Encryption}(pk, m)\\)**:
2423

25-
**\\(\operatorname{Decryption}(sk, c=(c_1, c_2))\\)**:
24+
1. Choose a random exponent \\(r \\leftarrow\\{0, 1, \dots, p-1\\}\\).
25+
2. The ciphertext is \\(c = (c_1, c_2) = (g^r, {pk}^r\\cdot m)\\).
2626

27-
1. The message is \\(m = c_2 \cdot c_1^{-1}\\).
27+
**\\(\\operatorname{Decryption}(sk, c=(c_1, c_2))\\)**:
2828

29-
## Implementing the Scheme
29+
1. Decryption computes \\(m = c_2 \\cdot c_1^{-sk}\\).
30+
31+
Decryption works because \\(c_1^{-sk} = (g^r)^{-sk} = (g^{sk})^{-r} = (pk)^{-r}\\) cancels out the \\(pk^r\\) term in \\(c_2\\).
32+
33+
## Basic implementation of ElGamal
34+
The operations outlined above can be quite directly transferred into Cryptimeleon.
35+
36+
```java
37+
public class ElGamalEncryptionScheme {
38+
protected Group group;
39+
protected GroupElement g;
40+
41+
public ElGamalEncryptionScheme(Group group) {
42+
this.group = group;
43+
this.g = group.getUniformlyRandomNonNeutral();
44+
}
45+
46+
public Zn.ZnElement generateSecretKey() {
47+
return group.getUniformlyRandomExponent();
48+
}
49+
50+
public GroupElement computePublicKey(Zn.ZnElement secretKey) {
51+
return g.pow(secretKey);
52+
}
53+
54+
public GroupElementVector encrypt(GroupElement plaintext, GroupElement publicKey) {
55+
var r = group.getUniformlyRandomExponent();
56+
return Vector.of(g.pow(r), publicKey.pow(r).op(plaintext));
57+
}
58+
59+
public GroupElement decrypt(GroupElementVector ciphertext, Zn.ZnElement secretKey) {
60+
return ciphertext.get(0).pow(secretKey.neg()).op(ciphertext.get(1));
61+
}
62+
}
63+
```
64+
65+
The whole scheme can then be tested as follows:
66+
```java
67+
public static void main(String[] args) {
68+
Group group = new Secp256k1();
69+
var scheme = new ElGamalEncryptionScheme(group);
70+
var secretKey = scheme.generateSecretKey();
71+
var publicKey = scheme.computePublicKey(secretKey);
72+
var plaintext = group.getUniformlyRandomElement();
73+
var ciphertext = scheme.encrypt(plaintext, publicKey);
74+
var plaintextRestored = scheme.decrypt(ciphertext, secretKey);
75+
if (plaintextRestored.equals(plaintext))
76+
System.out.println("Correctly decrypted plaintext "+plaintext);
77+
}
78+
```
79+
80+
To follow along, check out [https://github.com/cryptimeleon/java-demo](our Java demo project) and create a new class `ElGamalEncryptionScheme` as outlined above.
81+
82+
## Implementing the Scheme fully with data classes and interfaces
83+
Even though the implementation above can be considered complete, you may want to properly encapsulate the artifacts (keys, ciphertexts, etc.) into corresponding data classes.
84+
For a simple construction such as ElGamal, this is a somewhat useless exercise. However, for larger constructions with more complicated key structures, this step makes a lot of sense.
85+
For this reason, we showcase this step here.
3086

3187
We assume you have set up a new project in your IDE already, and added Craco as a dependency.
3288
Craco already includes the math library so you don't need to add that explicitly.
@@ -289,4 +345,4 @@ Using `Objects.equals()` and `Objects.hash()` is the easiest way to do this. The
289345

290346
# References
291347

292-
[Elg85] T. Elgamal, "A public key cryptosystem and a signature scheme based on discrete logarithms," in *IEEE Transactions on Information Theory*, vol. 31, no. 4, pp. 469-472, July 1985.
348+
[Elg85] T. Elgamal, "A public key cryptosystem and a signature scheme based on discrete logarithms," in *IEEE Transactions on Information Theory*, vol. 31, no. 4, pp. 469-472, July 1985.

0 commit comments

Comments
 (0)