Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Cipher和AES解密将产生208个解密字节,后跟垃圾_Java_Windows_Linux_Encryption - Fatal编程技术网

Java 使用Cipher和AES解密将产生208个解密字节,后跟垃圾

Java 使用Cipher和AES解密将产生208个解密字节,后跟垃圾,java,windows,linux,encryption,Java,Windows,Linux,Encryption,[编辑:不要试图理解整件事,也不要浪费时间阅读我所有的问题-只要记住解密已达到某个位置…并阅读我的答案,解释原因!] 我这里有一个恼人的问题我不知道如何解决 系统将加密数据写入文件,有些是序列化对象,有些是文本(XML)文件。在需要时进行解密的基类使用AES加密初始化密码,准备密钥(从文件读取),并且必须提供访问数据的方法: 获取InputStream的一种方法: public InputStream getInputStream(File pFile) throws IOException {

[编辑:不要试图理解整件事,也不要浪费时间阅读我所有的问题-只要记住解密已达到某个位置…并阅读我的答案,解释原因!]

我这里有一个恼人的问题我不知道如何解决

系统将加密数据写入文件,有些是序列化对象,有些是文本(XML)文件。在需要时进行解密的基类使用AES加密初始化密码,准备密钥(从文件读取),并且必须提供访问数据的方法:

获取InputStream的一种方法:

public InputStream getInputStream(File pFile) throws IOException {
  return
    new CipherInputStream(
      new BufferedInputStream(new FileInputStream(pFile)),
      getCipher(Cipher.DECRYPT_MODE)
    );
}
以及一种读取对象的方法,该方法仅将ObjectInputStream包装在从该方法派生的InputStream周围,并使用
ObjectInputStream.readObject()
读取该对象

现在。在软件系统中,一切都是这样工作的。 我想写的是一个命令行工具,帮助解密支持文件。所以,我使用了完全相同的方法来获取密码,我甚至使用了相同的类和在那里构建的InputStream

但是:不管我做什么:只有前208(!)字节被解密,其余的保持加密

我尝试使用字节缓冲区将数据从这个输入流“复制”到一个新的输出流,但我也尝试从数据中获取一个字符串,以查看调试器中发生了什么。=>效果总是一样的。直到这个208字节的“边界”,我看到的是明文,后面是垃圾

我不知道这里会出什么问题!有什么线索吗

密码是这样创建的:

public Cipher getCipher(int opMode) throws IOException {
    Cipher cipher = null;

    try {
        cipher = Cipher.getInstance("AES");
    } catch (NoSuchAlgorithmException e) {
        throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e);
    } catch (NoSuchPaddingException e) {
        throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e);
    }
    try {
        cipher.init(opMode, readKey());
    } catch (InvalidKeyException e) {
        throw new MdmInvalidKeyException();
    } catch (ClassNotFoundException e) {
        throw new MdmInvalidKeyException();
    } catch (NumberFormatException e) {
        throw new MdmInvalidKeyException();
    }
    return cipher;
}
public String readStream(InputStream is) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));

    StringBuffer sb = new StringBuffer();
    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line).append('\n');
        }
    } finally {
        reader.close();
    }

    return sb.toString();
}
下面是在软件系统中实际使用InputStream的代码:

String s = readStream(reader.getInputStream(file));
其中readStream的实现方式如下:

public Cipher getCipher(int opMode) throws IOException {
    Cipher cipher = null;

    try {
        cipher = Cipher.getInstance("AES");
    } catch (NoSuchAlgorithmException e) {
        throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e);
    } catch (NoSuchPaddingException e) {
        throw new MdmFatalInternalErrorException("Getting instance of cipher failed. Should never happen. BUG ", e);
    }
    try {
        cipher.init(opMode, readKey());
    } catch (InvalidKeyException e) {
        throw new MdmInvalidKeyException();
    } catch (ClassNotFoundException e) {
        throw new MdmInvalidKeyException();
    } catch (NumberFormatException e) {
        throw new MdmInvalidKeyException();
    }
    return cipher;
}
public String readStream(InputStream is) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));

    StringBuffer sb = new StringBuffer();
    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line).append('\n');
        }
    } finally {
        reader.close();
    }

    return sb.toString();
}
所有这些工作(在软件内)! 但是我尝试以同样的方式读取它失败了:字符串s包含208个解密字符,后跟垃圾

XML文件的编写完全是以相反的方式完成的,但这在这里并不重要,因为所显示的代码在系统中工作,而不是在我的简单复制程序中工作!我在那里使用完全相同的类!! 究竟为什么只有208个字符被解密

谢谢

编辑:现在很明显,只解密一定数量字节的效果取决于操作系统和机器!在使用32位Java 1.6 Update 20的Windows操作系统上,它无法解密-在使用64位Java 1.6 Update 18的Linux机器上,它可以工作


所以-这里有一个挑战:有人知道这是如何干扰输出的吗?

AES是一种分组密码,因此它必须加密精确大小(16字节)的块。当你加密数据时,你必须确保它可以被分成16字节的块;如果最后一个块短于此,则可以得到异常或垃圾(因为缓冲流的工作方式)。如果您不想为手动填充数据而烦恼,那么可以将密码设置为使用PKCS5P。除了调用Cipher.getInstance(“AES”)之外,还必须使用Cipher.getInstance(“AES/ECB/PKCS5Padding”),并且必须在两侧都这样做

另外,我建议使用CBC或CFB,这些模式需要一个初始化向量(salt),但它比使用ECB要好,ECB与不使用模式相同,这意味着您只需单独加密每个块,以便可以单独破解任何块。如果使用CBC或CFB,则要破解一个数据块,需要破解上一个数据块(CBC代表密码块链接)

最后但并非最不重要的是。。。如果您想在流上加密数据,最好使用诸如RC4之类的流密码,而不是分组密码。

这有点尴尬-但我把这个(已回答的!)问题留在这里,以防任何人遇到类似问题

我得到xx字节正确解密,然后是垃圾的原因很容易解释——真是我的耻辱

我们在Linux系统上加密了XML文件。系统内部的解密工作正常;但每当我试图在我的Windows机器上解密它们时,它都失败了

为什么??因为文件的扩展名是XML,而我的WinScp FTP工具将带有XML扩展名的文件视为文本文件,并将每个LF(#10)替换为CR LF(#13#10)

因此,在第一个愚蠢的CR字符被命中之前,解密一直正常工作!:-(

因此,我们了解到:除非你想找麻烦,否则千万不要给二进制文件加上文本文件的扩展名!
*叹气*

您没有显示执行从输入流读取或写入操作的代码。