Java 如何使用 XOR 开发 OTPInputStream

How to use XOR to develop a ​OTPInputStream​ in Java

我想在 Java 中开发一个 OTPInputStream 来扩展 InputStream 并获取另一个密钥数据输入流并提供一个流加密/解密输入stream.I需要开发一个测试程序来展示使用XOR和任意数据的OTPInputStream​的使用。

我尝试使用此代码,但遇到问题

java.io.FileInputStream cannot be cast to 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));  

    }
}

想想你想要的只是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() 将 return -1 并且正如指出的那样,一次读取一个字节很多IO 操作并会降低性能。您可以将数据保存在缓冲区中并像这样以另一种方式读取它:

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 个字节并将其存储在您的缓冲区中,然后您可以循环遍历缓冲区以执行您的逻辑。偏移值用于存储当前点在我们的输出中的位置。此外,您还必须确保 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 operation with two strings in java