Exercise Solution: Manual Kyber Computation
Given:
- q=17, A=[3752], s=[21], e=[11]
- r=[12], m=1, e1=[10], e2=1
Step 1: Public Key t=As+e(mod17)
Compute As:
As=[3752][21]=[(3)(2)+(5)(1)(7)(2)+(2)(1)]=[6+514+2]=[1116]
Add noise e:
t=As+e=[1116]+[11]=[1217](mod17)=[120]
t=[120]
Public key is pk=(A,t). Bob keeps sk=s=[2,1]T secret.
Step 2a: Ciphertext u=ATr+e1(mod17)
First, compute AT:
AT=[3572]
Compute ATr:
ATr=[3572][12]=[(3)(1)+(7)(2)(5)(1)+(2)(2)]=[3+145+4]=[179]
Add noise e1:
u=ATr+e1=[179]+[10]=[189](mod17)=[19]
u=[19]
Step 2b: Ciphertext v=tTr+e2+⌊q/2⌋⋅m(mod17)
Compute ⌊q/2⌋:
⌊217⌋=⌊8.5⌋=8
Compute tTr:
tTr=[120][12]=(12)(1)+(0)(2)=12
Add e2 and message encoding ⌊q/2⌋⋅m:
v=12+1+8⋅1=12+1+8=21(mod17)=4
v=4
Note: m=1 is encoded as ⌊q/2⌋=8 so it sits roughly in the "upper half" of Zq. If m=0 it adds nothing. This is how a single bit is hidden inside the ciphertext.
Step 3: Bob Computes v−sTu(mod17)
Compute sTu:
sTu=[21][19]=(2)(1)+(1)(9)=2+9=11
Subtract from v:
v−sTu=4−11=−7(mod17)=10
v−sTu=10
Why does this work? Expanding the math:v - s^T u = (t^T r + e_2 + \lfloor q/2 \rfloor m) - s^T(A^T r + e_1)$$$$= t^T r - s^T A^T r + e_2 - s^T e_1 + \lfloor q/2 \rfloor m
Since t=As+e, we have tT=sTAT+eT, so tTr−sTATr=eTr (small noise).
The result is approximately ⌊q/2⌋⋅m plus small noise terms.
Step 4: Recover m
We got v−sTu=10.
Now check: is 10 closer to 0 or to ⌊q/2⌋=8?
| Value | Distance to 0 | Distance to 8 |
|---|
| 10 | 10 | ∥10−8∥=2 ✅ |
Since 10 is closer to 8 (which represents m=1) than to 0 (which represents m=0):
m=1✓
Decoding rule:
- If result is close to 0 → m=0
- If result is close to ⌊q/2⌋=8 → m=1
The threshold is at q/4≈4.25. Values in [0,4] decode to 0; values in [5,12] decode to 1; and so on (wrapping around mod q).
The noise terms (eTr−sTe1) were small enough not to push us past the threshold — that's the whole design!
Step 5: Shared Key K=H(m)
Both Alice and Bob recovered the same m=1, so they compute:
K=H(1)
In real Kyber, H = SHA3-256 (or SHAKE-256 for the final KDF):
K=SHAKE256(K′∥H(c))
In this toy example with m=1:
K=H(1)=SHA3-256(1)=67... (some 256-bit value)
Both parties now share the same secret key K, which is used for symmetric encryption:
C=AES-GCM(K,message)
Full Solution Summary
| Step | Formula | Result |
|---|
| 1. Public key | t=As+e(mod17) | t=[12,0]T |
| 2a. Ciphertext u | u=ATr+e1(mod17) | u=[1,9]T |
| 2b. Ciphertext v | v=tTr+e2+8m(mod17) | v=4 |
| 3. Bob's decryption | v−sTu(mod17) | 10 |
| 4. Recover m | 10≈8=⌊q/2⌋ | m=1 ✅ |
| 5. Shared key | K=H(m) | K=H(1) |