【问题标题】:How to use XOR to develop a ​OTPInputStream​ in Java如何在 Java 中使用 XOR 开发一个​OTPInputStream​
【发布时间】:2020-06-02 05:08:06
【问题描述】:

我想用Java开发一个​OTPInputStream​,它扩展​了​InputStream​并接受另一个关键数据输入流并提供一个流加密/解密输入流。我需要开发一个测试程序来显示使用 XOR 和任意数据的OTPInputStream​

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

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

    }
}

【问题讨论】:

  • (CharSequence) file 你希望这个做什么?

标签: java bit-manipulation fileinputstream


【解决方案1】:

认为您想要的只是 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,并且正如指出的那样,一次读取一个字节是大量的 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 编码/解码来删除不可打印的字符:

  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

【讨论】:

  • 在不影响您的答案的情况下,指出一次读取一个字节在磁盘 IO 方面确实很昂贵,这将很有用。最好读取字节块或使用缓冲读取器。
  • 我有解密数据的问题,输出是正方形?初始化,
  • @Hala 你在加密数据,结果肯定有不可打印的字符,这没有错。
  • @Hala 抱歉已编辑。这是你的FileInputStream file。我只是输入并将我所有的FileInputStream 命名为fis
  • 我得到所有加密零输出
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多