gpt4 book ai didi

java - 使用 MessageDigest SHA-256 的 POI XSSF/XLSX 散列不确定性

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:37:50 25 4
gpt4 key购买 nike

使用 MessageDigest SHA-256 实现获取 POI XLSX 格式的确定性哈希值似乎存在问题,即使对于空的 ByteArray 流也是如此。在数百甚至数千次迭代之后,这种情况会随机发生。

用于重现问题的相关代码片段:

// TestNG FileTest:
@Test(enabled = true) // indeterminism at random iterations, such as 400 or 1290
public void emptyXLSXTest() throws IOException, NoSuchAlgorithmException {
final Hasher hasher = new HasherImpl();
boolean differentSHA256Hash = false;
for (int i = 0; i < 10000; i++) {
final ByteArrayOutputStream excelAdHoc1 = BusinessPlanInMemory.getEmptyExcel("xlsx");
final ByteArrayOutputStream excelAdHoc2 = BusinessPlanInMemory.getEmptyExcel("xlsx");

byte[] expectedByteArray = excelAdHoc1.toByteArray();
String expectedSha256 = hasher.sha256(expectedByteArray);
byte[] actualByteArray = excelAdHoc2.toByteArray();
String actualSha256 = hasher.sha256(actualByteArray);

if (!expectedSha256.equals(actualSha256)) {
differentSHA256Hash = true;
System.out.println("ITERATION: " + i);
System.out.println("EXPECTED HASH: " + expectedSha256);
System.out.println("ACTUAL HASH: " + actualSha256);
break;
}
}
Assert.assertTrue(differentSHA256Hash, "Indeterminism did not occur");
}

引用Hasher和POI代码:

// HasherImpl class:
public String sha256(final InputStream stream) throws IOException, NoSuchAlgorithmException {
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
final byte[] bytesBuffer = new byte[300000];
int bytesRead = -1;
while ((bytesRead = stream.read(bytesBuffer)) != -1) {
digest.update(bytesBuffer, 0, bytesRead);
}
final byte[] hashedBytes = digest.digest();
return bytesToHex(hashedBytes);
}

试图消除元数据(如创建时间)造成的不确定性,但无济于事:

// POI BusinessPlanInMemory helper class:
public static ByteArrayOutputStream getEmptyExcel(final String fileextension) throws IOException {
Workbook wb;

if (fileextension.equals("xls")) {
wb = new HSSFWorkbook();
}
else {
wb = new XSSFWorkbook();
final POIXMLProperties props = ((XSSFWorkbook) wb).getProperties();
final POIXMLProperties.CoreProperties coreProp = props.getCoreProperties();
coreProp.setCreated("");
coreProp.setIdentifier("1");
coreProp.setModified("");
}

wb.createSheet();

final ByteArrayOutputStream excelStream = new ByteArrayOutputStream();
wb.write(excelStream);
wb.close();
return excelStream;
}

HSSF/XLS 格式似乎不受所述问题的影响。有没有人知道,如果不是 POI 本身的错误,可能是什么原因造成的?基本上,上面的代码是指 https://poi.apache.org/spreadsheet/examples.html BusinessPlan example

感谢您的意见!

最佳答案

这不是一个明确的答案,但我怀疑会发生什么:

docx 和 xlsx 文件格式基本上是一堆压缩的 xml 文件。将它们重命名为 .zip 并使用您最喜欢的压缩工具打开时,可以很容易地看到这一点。

在检查由 word 创建的文件时,我注意到存档中包含的所有文件的更改时间戳始终是 1980-01-01 00:00:00 而在使用 POI 创建的文件中将显示文件创建的实际时间戳。

所以我怀疑当 excelAdHoc1excelAdHoc2 中的一个或多个文件之间存在时间戳差异时,就会出现您的问题。当创建一个或另一个文件时时钟切换到下一秒时,可能会发生这种情况。

这不会影响 XLS 文件,因为 HSSF 格式不是“压缩的 xml”类型,因此不包含任何可能具有不同时间戳的嵌套文件。

要在写入文件后更改时间戳,您可以尝试使用 `java.util.zip`` 包。我还没有测试过,但这应该可以解决问题:

ZipFile file = new ZipFile(pathToFile);
Enumeration<ZipEntry> e = file.entries();
while(e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
entry.setTime(0L);
}

关于java - 使用 MessageDigest SHA-256 的 POI XSSF/XLSX 散列不确定性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38698734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com