Как использовать XOR для разработки OTPInputStream в Java - PullRequest
0 голосов
/ 18 февраля 2020

Я хочу разработать OTPInputStream в Java, который расширяет InputStream и принимает другой входной поток ключевых данных и обеспечивает поток входного потока для шифрования / дешифрования. Мне нужно разработать тестовую программу чтобы показать использование OTPInputStream​, которое использует XOR и произвольные данные.

Я пытался с этим кодом, но у меня есть проблема, которая

java.io.FileInputStream не может быть приведена к java.lang.CharSequence

Что мне здесь делать?

public class Bitwise_Encryption {

    static String file = "" ;
    static String key = "VFGHTrbg";

    private static int[] encrypt(FileInputStream file, String key) {
        int[] output = new int[((CharSequence) file).length()];
        for(int i = 0; i < ((CharSequence) file).length(); i++) {
            int o = (Integer.valueOf(((CharSequence) file).charAt(i)) ^ Integer.valueOf(key.charAt(i % (key.length() - 1)))) + '0';
            output[i] = o;
        }
        return output;        
    }


    private static String decrypt(int[] input, String key) {
        String output = "";        
        for(int i = 0; i < input.length; i++) {
            output += (char) ((input[i] - 48) ^ (int) key.charAt(i % (key.length() - 1)));
        }
        return output;
    }


    public static void main(String args[]) throws FileNotFoundException {  
        FileInputStream file = new FileInputStream("directory");

        encrypt(file,key);
        //decrypt();
        int[] encrypted = encrypt(file,key);

        System.out.println("Encrypted Data is :");
        for(int i = 0; i < encrypted.length; i++)
            System.out.printf("%d,", encrypted[i]);

        System.out.println("");
        System.out.println("---------------------------------------------------");
        System.out.println("Decrypted Data is :");
        System.out.println(decrypt(encrypted,key));  

    }
}

1 Ответ

2 голосов
/ 18 февраля 2020

Подумайте, что вам нужно - просто file.read() и file.getChannel().size(), чтобы прочитать по одному символу за раз и получить размер файла

Попробуйте что-то вроде этого:

private static int[] encrypt(FileInputStream file, String key) {
  int fileSize = file.getChannel().size();
  int[] output = new int[fileSize];
  for(int i = 0; i < output.length; i++) {
    char char1 = (char) file.read();
    int o = (char1 ^ Integer.valueOf(key.charAt(i % (key.length() - 1)))) + '0';
    output[i] = o;
  }
  return output;        
}

Придется выполнить некоторую обработку ошибок, потому что file.read () вернет -1, если достигнут конец файла, и, как указано, чтение по одному байту за раз является большим количеством операций ввода-вывода и может снизить производительность. Вы можете хранить данные в буфере и читать их по-другому, например так:

private static int[] encrypt(FileInputStream file, String key) {
  int fileSize = file.getChannel().size();
  int[] output = new int[fileSize];

  int read = 0;
  int offset = 0;
  byte[] buffer = new byte[1024];
  while((read = file.read(buffer)) > 0) {
    for(int i = 0; i < read; i++) {
      char char1 = (char) buffer[i];
      int o = (char1 ^ Integer.valueOf(key.charAt(i % (key.length() - 1)))) + '0';
      output[i + offset] = o;
    }
    offset += read;
  }
  return output;        
}

Это будет считывать из файла 1024 байта за раз и сохранять их в буфере, затем вы можете l oop через буфер, чтобы сделать логи c. Значение смещения должно хранить, где в нашем выводе находится текущее место. Также вам нужно убедиться, что i + offset не превышает размер вашего массива.

ОБНОВЛЕНИЕ

После работы с ним; Я решил переключиться на Base64 Encoding / Decoding, чтобы удалить непечатаемые символы:

  private static String encrypt(InputStream file, String key) throws Exception {
    int read = 0;
    byte[] buffer = new byte[1024];
    try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
      while((read = file.read(buffer)) > 0) {
        baos.write(buffer, 0, read);
      }
      return base64Encode(xorWithKey(baos.toByteArray(), key.getBytes()));
    }
  }

  private static String decrypt(String input, String key) {
    byte[] decoded = base64Decode(input);
    return new String(xorWithKey(decoded, key.getBytes()));
  }

  private static byte[] xorWithKey(byte[] a, byte[] key) {
    byte[] out = new byte[a.length];
    for (int i = 0; i < a.length; i++) {
      out[i] = (byte) (a[i] ^ key[i%key.length]);
    }
    return out;
  }

  private static byte[] base64Decode(String s) {
    return Base64.getDecoder().decode(s.trim());
  }

  private static String base64Encode(byte[] bytes) {
    return Base64.getEncoder().encodeToString(bytes);
  }

Этот метод более понятен и не требует знания размера InputStream или каких-либо преобразований символов. Он читает ваш InputStream в OutputStream для выполнения кодирования Base64, а также для удаления непечатаемых символов.

Я проверил это, и он работает как для шифрования, так и для дешифрования.

Я получил идея из этого ответа:

операция XOR с двумя строками в java

...