We will use a scaled-down version of Kyber called Baby Kyber, following this page:
s: a vector of polynomials with random small coefficients -- this is the private key
q: a modulus for coefficients
f: a modulus for polynomials, set to x4 + 1
A: a matrix of random polynomials
e: a vector of small random error values
t: a calculated vector of polynomialsThe public key is (A, t)
s = ( -x3 -x2 +x, -x3 -x)
q = 17Next, we generate a matrix of random polynomials, called called A. The coefficients are taken modulus q.
We'll use these errors:
A = [
6x3 +16x2 +16x + 11 9x3 +4x2 +6x + 3 5x3 +3x2 +10x + 1 6x3 +x2 +9x + 15 ]
e = ( x2, x2 -x)Now we calculate t by matrix multiplication and addition:
t = As + e
Calculating the top term of t:
t = [
6x3 +16x2 +16x + 11 9x3 +4x2 +6x + 3 5x3 +3x2 +10x + 1 6x3 +x2 +9x + 15 ] [
-x3 -x2 +x -x3 -x ] + [
x2 x2 -x ]
( 6x3 +16x2 +16x + 11 ) ( -x3 -x2 +x ) + ( 9x3 +4x2 +6x + 3 ) ( -x3 -x ) + x2 =All polynomials are calculated modulus f = x4 + 1, so we can replace all occurrences of x4 with -1, giving:
-6x6 -6x5 +6x4 -16x5 -16x4 +16x3 -16x4 -16x3 +16x2 -11x3 -11x2 +11x -9x6 -9x4 -4x5 -4x3 -6x4 -6x2 -3x3 -3x +x2
=-15x6 -26x5 -41x4 -18x3 +8x
Finally, we take all polynomial coefficients modulus q = 17, giving:
15x2 +26x +41 -18x3 +8x = -18x3 +15x2 +34x + 41
Calculating the bottom term of t:
16x3 +15x2 + 7
( 5x3 +3x2 +10x + 1 ) ( -x3 -x2 +x ) + ( 6x3 +x2 +9x + 15 ) ( -x3 -x ) + x2 -x =All polynomials are calculated modulus f = x4 + 1, so we can replace all occurrences of x4 with -1, giving:
-5x6 -5x5 +5x4 -3x5 -3x4 +3x3 -10x4 -10x3 +10x2 -x3 -x2 +x -6x6 -6x4 -x5 -x3 -9x4 -9x2 -15x3 -15x +x2 -x
=-11x6 -9x5 -23x4 -24x3 +x2 -15x
Finally, we take all polynomial coefficients modulus q = 17, giving:
11x2 +9x +23 -24x3 +x2 -15x = -24x3 +12x2 -6x + 23
The final result is:
10x3 +12x2 +11x + 6
t = [
16x3 +15x2 + 7 10x3 +12x2 +11x + 6 ]
Private key: s = ( -x3 -x2 +x, -x3 -x)Public key: (A, t), where
A = [
6x3 +16x2 +16x + 11 9x3 +4x2 +6x + 3 5x3 +3x2 +10x + 1 6x3 +x2 +9x + 15 ] t = ( 16x3 +15x2 + 7, 10x3 +12x2 +11x + 6)
C 800.1: Public Key (10 pts)
Use the values below to calculate t:
A = [
x3 +4x2 + 1 3x3 +12x2 +14x + 5 3x3 +12x2 +2x 11x3 +4x2 +2x + 5 ] s = ( x3 -x, -x3 -x2 -x)To construct the flag, append all the non-zero coefficients, as shown below.e = ( x3 +x2 +x, -x2 -x)
If t were:
t = ( 16x3 +15x2 + 7, 10x3 +12x2 +11x + 6)The key would be 161571012116.
So we'll use a simple set of Python functions from this page:
Adventures in PQC: Exploring Kyber in Python - Part I
Notice that polynomial coefficients are in reverse order, starting with x0, then x1, then x2, etc.
!wget https://samsclass.info/141/proj/kyber.pyx
!mv kyber.pyx kyber.py
from kyber import *
# Baby Kyber params
q = 17 # plain modulus
f = [1, 0, 0, 0, 1] # poly modulus, x**4 + 1
s = [[0, 1, -1, -1], [0, -1, 0, -1]] # secret key, [-x**3-x**2+x, -x**3-x]
A = [[[11, 16, 16, 6], [3, 6, 4, 9]], [[1, 10, 3, 5], [15, 9, 1, 6]]]
e = [[0, 0, 1, 0], [0, -1, 1, 0]] # noise
t = add_vec(mul_mat_vec_simple(A, s, f, q), e, q)
print("t:", t)
As shown below, it calculates t correctly.
Again, notice that the order of the coefficients is reversed in this Python implementation,
C 800.2: Public Key (10 pts)
Use the values below to calculate t:
A = [
6x3 +1x2 + 13x + 3 9x3 +2x2 +11x + 16 9x3 +5x2 +5x + 10 9x3 +8x2 +7x + 6 ] s = ( -x3 +x2 +x, x3 -x2 +x)To construct the flag, append all the non-zero coefficients, as shown below.e = ( -x3 -x, x3 -x2)
q = 17
If t were:
t = ( 16x3 +15x2 + 7, 10x3 +12x2 +11x + 6)The key would be 161571012116.
A randomizer polynomial vector r with random small coefficientsFor this example, we'll use:
An error polynomial vector e1 with random small coefficients
An error polynomial e2 with random small coefficients
A message composed of four bits
r = ( -x3 +x2, x3 +x2 -1)We encode the message, using the bits as coefficients for a polynomial:e1 = ( x2 +x, x2)
e2 = -x3 -x2
message = 1011
Encoded message (1011) = 1x3 +0x2 +1x +1 = x3 +x +1To make the message large enough to overcome the errors, we scale it by multiplying by half the modulus q, rounded up, which is 9 for our example.
The final scaled encoded message is:
m = 9x3 +9x +9The encryption process is:
u = ATr + e1Errors are added, so the answer is different each time.v = tTr + e2 +m
Decryption uses this formula:
mn = v - sTuThe result is noisy because of the errors. This is why each coefficient encodes only one bit, despite having values from 0 to 16.
To complete the decryption process, coefficients correspond to bits like this:
# Baby Kyber params
q = 17 # plain modulus
f = [1, 0, 0, 0, 1] # poly modulus, x**4 + 1
s = [[0, 1, -1, -1], [0, -1, 0, -1]] # secret key, [-x**3-x**2+x, -x**3-x]
A = [[[11, 16, 16, 6], [3, 6, 4, 9]], [[1, 10, 3, 5], [15, 9, 1, 6]]]
e = [[0, 0, 1, 0], [0, -1, 1, 0]] # noise
t = add_vec(mul_mat_vec_simple(A, s, f, q), e, q)
m_b = [1, 1, 0, 1] # message in binary
r = [[0, 0, 1, -1], [-1, 0, 1, 1]] # blinding vector for encrypt
e_1 = [[0, 1, 1, 0], [0, 0, 1, 0]] # noise vector for encrypt
e_2 = [0, 0, -1, -1] # noise poly for encrypt
u, v = encrypt(A, t, m_b, f, q, r, e_1, e_2)
print("Encrypted message (u, v):", u, v)
m_b2 = decrypt(s, u, v, f, q)
print("Decrypted message:", m_b2)
As shown below,
encryption produces random-appearing numbers, but
they decrypt to the correct message.
C 800.3: Encryption (10 pts)
Use the values below to calculate t:
A = [
6x3 +1x2 + 13x + 3 9x3 +2x2 +11x + 16 9x3 +5x2 +5x + 10 9x3 +8x2 +7x + 6 ] s = ( -x3 +x2 +x, x3 -x2 +x)e = ( -x3 -x, x3 -x2)
q = 17
r = ( -x3 -x2, x3 -x2 -1)To construct the flag, concatenate all the non-zero coefficients covered by a green rectangle in the image below.e1 = ( -x2 +x, -x2)
e2 = x3 +x2
message = 1010
This will form a seven-digit number.
A private key sWe'll also use the coefficient modulus q and the polynomial modulus f, at the same values used above. For this example, we'll use:
An encrypted message (u, v)
s = ( -x3 -x2 +x, -x3 -x)Here's the encrypted message we created above, in our Python format:
u, v = [[3, 10, 11, 11], [11, 13, 4, 4]], [15, 8, 6, 7]
To perform the decryption,
in Google Colab, execute these commands.
q = 17
f = [1, 0, 0, 0, 1]
s = [[0, 1, -1, -1], [0, -1, 0, -1]]
u, v = [[3, 10, 11, 11], [11, 13, 4, 4]], [15, 8, 6, 7]
m_b2 = decrypt(s, u, v, f, q)
print("Decrypted message:", m_b2)
As shown below, the message decrypts to the
correct value of 1011, with the bits in reverse
order.
C 800.4: Decryption (10 pts)
Use the values below to calculate t:s = ( x2 +1, x3 +x2 +x +1)The flag is the decrypted message as a four-bit binary number, like 1011Encrypted message (u, v): [[3, 15, 5, 2], [6, 4, 6, 9]] [15, 8, 11, 6]
Posted 11-27-23 by Sam Bowne
Flag 1 values restored 12-10-23