Почему символы в моем шифровании RING-LWE меняются местами?JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Почему символы в моем шифровании RING-LWE меняются местами?

Сообщение Anonymous »

Я разрабатываю приложение безопасного чата с использованием Ring-LWE для своего проекта по криптографии и ценным бумагам с использованием Java в среде клиент-сервер. На данный момент я реализовал логику совместного использования ключей, а также шифрования и дешифрования, однако символы заменяются местами.
Вот код и примеры выходных данных, которые я получаю:
Client.java с кодом Ring-LWE:

Код: Выделить всё

    import java.io.*;
import java.net.*;
import java.util.Arrays;
import java.util.Random;
import javax.sound.sampled.*;
import java.util.Base64;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class ChatClient {
private BufferedReader in;
private PrintWriter out;
private BufferedReader console;

private String clientName;
private String targetName;

private RingLWE ringLWE;
private int[] myPublicA;
private int[] myPublicB;

private int[] targetPublicA;
private int[] targetPublicB;

private boolean chatting = false;
private boolean keyExchangeCompleted = false;

private ByteArrayOutputStream voiceOutputStream;
private byte[] receivedVoiceData;
private boolean isRecording = false;
private TargetDataLine microphone;
private AudioFormat audioFormat;

private Map receivedFiles = new ConcurrentHashMap();

public static void main(String[] args) {
new ChatClient().start();
}

private void start() {
String serverAddress = "localhost";
int port = 5000;

try (Socket socket = new Socket(serverAddress, port)) {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
console = new BufferedReader(new InputStreamReader(System.in));

System.out.println(in.readLine());
clientName = console.readLine();
out.println(clientName);

String response = in.readLine();
if (response.startsWith("Name already taken")) {
System.out.println(response);
return;
}
System.out.println(response);

ringLWE = new RingLWE();
int[][] publicKey = ringLWE.generatePublicKey();
myPublicA = publicKey[0];
myPublicB = publicKey[1];

new ServerListener().start();

String message;
while ((message = console.readLine()) != null) {
if (message.startsWith("/accept ")) {
String fromClient = message.substring(8).trim();
out.println("CHATRESPONSE:" + fromClient + ":ACCEPT");
targetName = fromClient;
chatting = true;
keyExchangeCompleted = false;
String publicKeyStr = serializePublicKey(myPublicA, myPublicB);
out.println("KEYEXCHANGERESPONSE:" + targetName + ":" + publicKeyStr);
}
else if (message.startsWith("/file transfer")) {
String[] tokens = message.split(" ", 3);
if (tokens.length < 3) {
System.out.println("Usage: /file transfer ");
continue;
}
String filePath = tokens[2].trim();
if (!chatting) {
System.out.println("You are not in a chat.  Start a chat before transferring files.");
continue;
}
File fileToSend = new File(filePath);
if (!fileToSend.exists() || !fileToSend.isFile()) {
System.out.println("File does not exist or is not a valid file: " + filePath);
continue;
}
String fileName = fileToSend.getName();
byte[] fileBytes;
try {
fileBytes = Files.readAllBytes(fileToSend.toPath());
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
continue;
}

String encryptedFileData = encryptFileData(fileBytes);
if (encryptedFileData != null) {
out.println("FILETRANSFER:" + targetName + ":" + fileName + ":" + encryptedFileData);
System.out.println("File '" + fileName + "' sent to " + targetName + ".");
} else {
System.out.println("Failed to encrypt the file.");
}
}
else if (message.startsWith("/file download")) {
String[] tokens = message.split(" ", 4);
if (tokens.length < 4) {
System.out.println("Usage: /file download  ");
continue;
}
String fileName = tokens[2].trim();
String savePath = tokens[3].trim();
if (!chatting) {
System.out.println("You are not in a chat.");
continue;
}
if (!receivedFiles.containsKey(fileName)) {
System.out.println("No such file received: " + fileName);
continue;
}
String encryptedFileData = receivedFiles.get(fileName);
byte[] decryptedFileData = decryptFileData(encryptedFileData);
if (decryptedFileData != null) {
File saveFile = new File(savePath);
try {
Files.write(saveFile.toPath(), decryptedFileData);
System.out.println("File '" + fileName + "' has been saved to " + saveFile.getAbsolutePath());
receivedFiles.remove(fileName);
} catch (IOException e) {
System.out.println("Error saving file: " + e.getMessage());
}
} else {
System.out.println("Failed to decrypt the file.");
}
}
else if (message.startsWith("/decline ")) {
String fromClient = message.substring(9).trim();
out.println("CHATRESPONSE:" + fromClient + ":DECLINE");
System.out.println("You declined the chat request from " + fromClient + ".");
}
else if (message.startsWith("/voice ")) {
String command = message.substring(7).trim();
if (command.equalsIgnoreCase("record")) {
if (!chatting) {
System.out.println("You are not in a chat.  Start a chat before recording voice messages.");
continue;
}
if (isRecording) {
System.out.println("Already recording.");
continue;
}
startVoiceRecording();
}
else if (command.equalsIgnoreCase("stop")) {
if (!isRecording) {
System.out.println("Not currently recording.");
continue;
}
stopVoiceRecording();
}
else {
System.out.println("Unknown voice command. Use '/voice record' or '/voice stop'.");
}
}
else if (message.startsWith("/play")) {
playReceivedVoiceMessage();
}
else if (message.equalsIgnoreCase("/help")) {
printHelp();
}
else if (!chatting) {
if (message.equalsIgnoreCase("exit")) {
out.println("exit");
break;
}
targetName = message.trim();
out.println("CHAT:" + targetName);
System.out.println("Chat request sent to " + targetName + ".  Waiting for response...");
}
else {
if (message.equalsIgnoreCase("/leave")) {
out.println("/leave");
chatting = false;
keyExchangeCompleted = false;
targetName = null;
targetPublicA = null;
targetPublicB = null;
System.out.println("You have left the chat.");
continue;
}
if (message.startsWith("/")) {
System.out.println("Unknown command.");
continue;
}
if (!keyExchangeCompleted) {
System.out.println("Key exchange not completed.");
continue;
}
byte[] messageBytes = message.getBytes("UTF-8");
StringBuilder encryptedMessages = new StringBuilder();
for (byte b : messageBytes) {
int[] ciphertext = ringLWE.encryptByte(b & 0xFF, targetPublicA, targetPublicB);
encryptedMessages.append(serializeCiphertext(ciphertext)).append(";");
}
out.println("MESSAGE:" + targetName + ":" + encryptedMessages.toString());
}
}

} catch (IOException e) {
System.err.println("IOException in client: " + e.getMessage());
}
}

private String serializePublicKey(int[] a, int[] b) {
StringBuilder sb = new StringBuilder();
sb.append(Arrays.toString(a));
sb.append("|");
sb.append(Arrays.toString(b));
return sb.toString();
}

private String encryptFileData(byte[] fileData) {
try {
StringBuilder encryptedData = new StringBuilder();
for (byte b : fileData) {
int[] ciphertext = ringLWE.encryptByte(b & 0xFF, targetPublicA, targetPublicB);
encryptedData.append(serializeCiphertext(ciphertext)).append(";");
}
return Base64.getEncoder().encodeToString(encryptedData.toString().getBytes("UTF-8"));
} catch (Exception e) {
System.out.println("Error encrypting file data: " + e.getMessage());
return null;
}
}

private void deserializePublicKey(String publicKeyStr) {
try {
String[] parts = publicKeyStr.split("\\|");
String aStr = parts[0].replaceAll("[\\[\\] ]", "");
String bStr = parts[1].replaceAll("[\\[\\] ]", "");
String[] aTokens = aStr.split(",");
String[] bTokens = bStr.split(",");
targetPublicA = new int[aTokens.length];
targetPublicB = new int[bTokens.length];
for (int i = 0; i < aTokens.length; i++) {
targetPublicA[i] = Integer.parseInt(aTokens[i]);
}
for (int i = 0; i < bTokens.length; i++) {
targetPublicB[i] = Integer.parseInt(bTokens[i]);
}
} catch (Exception e) {
System.out.println("Error deserializing public key: " + e.getMessage());
}
}

private String serializeCiphertext(int[] ciphertext) {
return Arrays.toString(ciphertext).replaceAll("[\\[\\] ]", "");
}

private int[] deserializeCiphertext(String ciphertextStr) {
String[] tokens = ciphertextStr.split(",");
int[] ciphertext = new int[tokens.length];
for (int i = 0; i < tokens.length;  i++) {
ciphertext[i] = Integer.parseInt(tokens[i]);
}
return ciphertext;
}

private class ServerListener extends Thread {
public void run() {
try {
String serverMsg;
while ((serverMsg = in.readLine()) != null) {
if (serverMsg.startsWith("CHATREQUEST:")) {
String fromClient = serverMsg.substring(12);
System.out.println("You have a chat request from " + fromClient + ".");
System.out.println("Type '/accept " + fromClient + "' to accept, or '/decline " + fromClient + "' to decline.");
}
else if (serverMsg.startsWith("CHATRESPONSE:")) {
String[] parts = serverMsg.split(":", 3);
if (parts.length == 3) {
String targetNameResponse = parts[1];
String response = parts[2];
if (targetNameResponse.equals(targetName)) {
if (response.equalsIgnoreCase("ACCEPT")) {
System.out.println(targetName + " accepted your chat request.");
chatting = true;
keyExchangeCompleted = false;
String publicKeyStr = serializePublicKey(myPublicA, myPublicB);
out.println("KEYEXCHANGE:" + targetName + ":" + publicKeyStr);
} else {
System.out.println(targetName + " declined your chat request.");
targetName = null;
}
}
}
}
else if (serverMsg.startsWith("FILETRANSFERFROM:")) {
String[] parts = serverMsg.split(":", 4);
if (parts.length == 4) {
String fromClient = parts[1];
String fileName = parts[2];
String encryptedFileData = parts[3];
System.out.println("You have received a file '" + fileName + "' from " + fromClient + ".");
System.out.println("To download the file, use: /file download " + fileName + " ");
receivedFiles.put(fileName, encryptedFileData);
} else {
System.out.println("Received an invalid FILETRANSFERFROM message.");
}
}
else if (serverMsg.startsWith("KEYEXCHANGEFROM:")) {
String[] parts = serverMsg.split(":", 3);
String fromClient = parts[1];
String publicKeyStr = parts[2];
if (fromClient.equals(targetName)) {
if (!keyExchangeCompleted) {
deserializePublicKey(publicKeyStr);
if (targetPublicA == null || targetPublicB == null) {
System.out.println("Failed to parse public key from " + targetName);
continue;
}
String publicKeyStrOut = serializePublicKey(myPublicA, myPublicB);
out.println("KEYEXCHANGERESPONSE:" + fromClient + ":" + publicKeyStrOut);
System.out.println("Received public key from " + targetName + ".  Sending our public key.");
keyExchangeCompleted = true;
System.out.println("Key exchange completed with " + targetName);
}
}
}
else if (serverMsg.startsWith("KEYEXCHANGERESPONSEFROM:")) {
String[] parts = serverMsg.split(":", 3);
String fromClient = parts[1];
String publicKeyStr = parts[2];
if (fromClient.equals(targetName)) {
if (!keyExchangeCompleted) {
deserializePublicKey(publicKeyStr);
if (targetPublicA == null || targetPublicB == null) {
System.out.println("Failed to parse public key from " + targetName);
continue;
}
keyExchangeCompleted = true;
System.out.println("Key exchange completed with " + targetName);
}
}
}
else if (serverMsg.startsWith("MESSAGEFROM:")) {
String[] parts = serverMsg.split(":", 3);
String fromClient = parts[1];
String encryptedMessages = parts[2];
if (fromClient.equals(targetName)) {
String[] ciphertexts = encryptedMessages.split(";");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (String cStr : ciphertexts) {
if (cStr.isEmpty()) continue;
int[] ciphertext = deserializeCiphertext(cStr);
int decryptedByte = ringLWE.decryptByte(ciphertext);
baos.write(decryptedByte);
}
String decryptedMessage = new String(baos.toByteArray(), "UTF-8");
System.out.println(targetName + ": " + decryptedMessage);
}
}
else if (serverMsg.startsWith("VOICEMESSAGEFROM:")) {
String[] parts = serverMsg.split(":", 3);
String fromClient = parts[1];
String encryptedVoiceData = parts[2];
if (fromClient.equals(targetName)) {
byte[] decryptedVoice = decryptVoiceMessage(encryptedVoiceData);
if (decryptedVoice != null) {
receivedVoiceData = decryptedVoice;
System.out.println("You have received a voice message from " + fromClient + ".  Type '/play' to listen.");
} else {
System.out.println("Failed to decrypt voice message from " + fromClient + ".");
}
}
}
else if (serverMsg.startsWith("CHATENDED:")) {
String leftClient = serverMsg.substring(10);
if (leftClient.equals(targetName)) {
System.out.println("SYSTEM: " + targetName + " has left the chat.");
chatting = false;
keyExchangeCompleted = false;
targetName = null;
targetPublicA = null;
targetPublicB = null;
}
}
else if (serverMsg.startsWith("SYSTEM:")) {
System.out.println(serverMsg);
}
else if (serverMsg.startsWith("ERROR:")) {
System.out.println(serverMsg);
}
else {
System.out.println(serverMsg);
}
}
} catch (IOException e) {
System.err.println("Connection closed.");
}
}
}

private void startVoiceRecording() {
try {
audioFormat = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Microphone not supported.");
return;
}
microphone = (TargetDataLine) AudioSystem.getLine(info);
microphone.open(audioFormat);
microphone.start();

voiceOutputStream = new ByteArrayOutputStream();
isRecording = true;

Thread recordingThread = new Thread(() -> {
byte[] buffer = new byte[4096];
while (isRecording) {
int bytesRead = microphone.read(buffer, 0, buffer.length);
if (bytesRead > 0) {
voiceOutputStream.write(buffer, 0, bytesRead);
}
}
try {
voiceOutputStream.close();
} catch (IOException e) {
//ignore
}
});

recordingThread.start();
System.out.println("Recording started.  Type '/voice stop' to stop recording.");

} catch (LineUnavailableException e) {
System.out.println("Microphone unavailable: " + e.getMessage());
}
}

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;
}
}
}

Вывод:
hello -> gelko
help -> gekp
У меня так Far пытался увеличить скалярный коэффициент и коэффициенты ошибок, но, похоже, это не помогло.
Пожалуйста, помогите мне это исправить.
Спасибо!
(PS. Я знаю, Ring-LWE это плохая идея для шифрования голоса и файлов в реальном времени. только для целей проекта.)

Подробнее здесь: https://stackoverflow.com/questions/792 ... ng-swapped
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Почему символы в моем шифровании RING-LWE меняются местами?
    Anonymous » » в форуме JAVA
    0 Ответы
    18 Просмотры
    Последнее сообщение Anonymous
  • Почему символы в моем шифровании RING-LWE меняются местами?
    Anonymous » » в форуме JAVA
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Поменяйте местами первое и последнее слова и поменяйте местами все средние символы.
    Anonymous » » в форуме JAVA
    0 Ответы
    14 Просмотры
    Последнее сообщение Anonymous
  • Поменяйте местами первое и последнее слова и поменяйте местами все средние символы.
    Anonymous » » в форуме JAVA
    0 Ответы
    18 Просмотры
    Последнее сообщение Anonymous
  • Поменяйте местами первое и последнее слова и поменяйте местами все средние символы.
    Anonymous » » в форуме JAVA
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous

Вернуться в «JAVA»