Reputation: 79
I'm developing a Secure Chat Application using Ring-LWE for my cryptography and securities project using Java in a Client-Server environment. I have so far implemented the logic behind the key sharing along with the encryption and decryption, however characters are being swapped out. Here's the code and sample outputs I am recieving:
Client.java with the Ring-LWE code:
class RingLWE {
private final int n = 512;
private final int q = 12289;
private final int scalingFactor = q / 256; //48
private int[] s;
public RingLWE() {
Random random = new Random();
s = new int[n];
for (int i = 0; i < n; i++) {
s[i] = random.nextInt(3) - 1; // Coefficients in {-1, 0, 1}
}
}
// public key (a, b)
public int[][] generatePublicKey() {
Random random = new Random();
int[] a = new int[n];
int[] e = new int[n];
int[] b = new int[n];
// polynomial a
for (int i = 0; i < n; i++) {
a[i] = random.nextInt(q);
}
// error polynomial e
for (int i = 0; i < n; i++) {
e[i] = random.nextInt(3) - 1; // Coefficients in {-1, 0, 1}
}
// b = a * s + e mod q
b = polyAdd(polyMul(a, s), e);
for (int i = 0; i < n; i++) {
b[i] = modq(b[i]);
}
return new int[][]{a, b};
}
public int[] encryptByte(int message, int[] a, int[] b) {
Random random = new Random();
// polynomial r
int[] r = new int[n];
for (int i = 0; i < n; i++) {
r[i] = random.nextInt(3) - 1; // Coefficients in {-1, 0, 1}
}
// error polynomials e1 and e2
int[] e1 = new int[n];
int[] e2 = new int[n];
for (int i = 0; i < n; i++) {
e1[i] = random.nextInt(3) - 1;
e2[i] = random.nextInt(3) - 1;
}
// u = a * r + e1 mod q
int[] u = polyAdd(polyMul(a, r), e1);
for (int i = 0; i < n; i++) {
u[i] = modq(u[i]);
}
int[] m = new int[n];
m[0] = message;
// v = b * r + e2 + m * scalingFactor mod q
int[] scaledM = scalarMul(m, scalingFactor);
int[] v = polyAdd(polyAdd(polyMul(b, r), e2), scaledM);
for (int i = 0; i < n; i++) {
v[i] = modq(v[i]);
}
int[] ciphertext = new int[2 * n];
System.arraycopy(u, 0, ciphertext, 0, n);
System.arraycopy(v, 0, ciphertext, n, n);
return ciphertext;
}
public int decryptByte(int[] ciphertext) {
int[] u = new int[n];
int[] v = new int[n];
System.arraycopy(ciphertext, 0, u, 0, n);
System.arraycopy(ciphertext, n, v, 0, n);
// m' = v - u * s mod q
int[] us = polyMul(u, s);
int[] mPrime = polySub(v, us);
for (int i = 0; i < n; i++) {
mPrime[i] = modq(mPrime[i]);
}
int decryptedMessage = (int) Math.round((double) mPrime[0] / scalingFactor);
decryptedMessage = decryptedMessage % 256;
if (decryptedMessage < 0) decryptedMessage += 256;
return decryptedMessage;
}
// Polynomial multiplication modulo x^n + 1
private int[] polyMul(int[] a, int[] b) {
int[] result = new int[n];
for (int i = 0; i < n; i++) {
long sum = 0;
for (int j = 0; j < n; j++) {
int index = (i - j) % n;
if (index < 0) index += n;
int sign = (((i - j) >= 0) ? 1 : -1);
sum += (long) sign * a[j] * b[index];
}
result[i] = modq((int) sum);
}
return result;
}
private int[] polyAdd(int[] a, int[] b) {
int[] result = new int[n];
for (int i = 0; i < n; i++) {
result[i] = modq(a[i] + b[i]);
}
return result;
}
private int[] polySub(int[] a, int[] b) {
int[] result = new int[n];
for (int i = 0; i < n; i++) {
result[i] = modq(a[i] - b[i]);
}
return result;
}
private int[] scalarMul(int[] a, int scalar) {
int[] result = new int[n];
for (int i = 0; i < n; i++) {
result[i] = modq(a[i] * scalar);
}
return result;
}
private int modq(int x) {
int result = x % q;
if (result < 0) result += q;
return result;
}
}
}
Output:
I have so far tried increasing the scalar factor and error coefficients, but that does not seem to fix it.
I'm aware Ring-LWE is a bad idea for real time voice and file encryption. This is only for project purposes.
Upvotes: 1
Views: 63