- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
使用 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 创建的文件中将显示文件创建的实际时间戳。
所以我怀疑当 excelAdHoc1
和 excelAdHoc2
中的一个或多个文件之间存在时间戳差异时,就会出现您的问题。当创建一个或另一个文件时时钟切换到下一秒时,可能会发生这种情况。
这不会影响 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/
我有一个 Java 方法,我正在将其移植到 C#,该方法使用盐对字符串进行哈希处理。该方法执行如下操作。 private byte[] hash(byte[] bytes, byte[] salt)
我想使用 MessageDigest 获取 MD5 哈希值,但出现错误。 import java.security.MessageDigest; public class dn { public
我在项目中使用 MessageDigest 计算 md5 签名,但在性能测试期间它抛出 ArrayIndexOutOfBoundsException。 我发现一些帖子表明这是因为 MessageDig
我正在使用 Java 的 MessageDigest 来做一个哈希项目。我想与随机生成的字符串产生的哈希值产生冲突。我已经验证我的字符串确实是随机的。然而,当我输出摘要时,由于某种原因,它总是以“[B
示例一: FileInputStream fis = new FileInputStream(path); MessageDigest digest = MessageDigest.getInstan
我无法让 MessageDigest 工作,程序给我两个错误:不支持的编码异常,NoSuchAlgorithmException byte[] bytesOfchat_key = "lol".get
我有这个在 Java 中加密密码的函数,但是当我调用MessageDigest,即使我使用相同的密码调用它,它每次都会返回不同的结果。我想知道我是否以某种方式将其初始化错误。 public Strin
我遇到了 MessageDigest 在不同计算机上返回不同哈希值的问题。 一台计算机在 Windows Vista 上运行 32 位 Java,另一台在 Mac OS 上运行 64 位 Java。我
我盲目地遵循了 OWASP 关于在 java 中生成哈希的建议 (see here),我不确定我是否正确地做到了。具体来说,我不确定MessageDigest.reset() 的目的和效果。 ,因此何
MessageDigest 类实现了 SHA-1 算法(以及许多其他算法)。 SHA-1 算法允许使用不同的“种子”或初始摘要。参见 SHA-1 Psuedocode 算法初始化变量,或种子: Ini
我自己编写了简化的 MessageDigest 包装器,现在我想知道它是否是线程安全的。 public final class SimpleIMD implements ImmutableMessag
我有一个自定义类加载器,在它的构造函数中我有以下行。 MessageDigest.getInstance("MD5") 当我使用自定义类加载器作为系统类加载器运行示例主应用程序时,出现以下错误。 Er
我非常无聊,所以我正在制作一个实验性的暴力破解器。不过,我在使用 MD5 时遇到了一些问题。我得到两个截然不同的输出, 1aabac6d068eef6a7bad3fdf50a05cc8 -7d881f
MessageDigest 接受一个字符串,表示您要散列时要使用的算法。 I've used some of the code here在我的 Android 设备上积累相当大的 220 个“算法”列
是否有可能保存 MessageDigest 对象的内部状态?我想将它保存在数据库中,所以只能使用原始数据,如 String、int、byte[]。 我想要实现的是能够接收一个碎片文件(在很长一段时间内
我正在尝试使用 Java 中的 MessageDigest 获取字符串的哈希值,但每次的值都不同。当我运行该程序两次时,它会再次得到完全不同的答案。 MessageDigest md
我脑后的某些东西告诉我,我在这里遗漏了一些明显的东西。 我正在将一个现有的 java 项目与第三方 api 集成,该 api 使用 api key 的 md5 哈希进行身份验证。它对我不起作用,在调试
MessageDigest 中的 digest() 方法不应该总是为相同的输入提供相同的哈希值吗? 我试过了,每次我都得到相同输入的不同哈希值集 md5 = MessageDigest.getInst
我有一个使用自定义系统类加载器的应用程序,由 Djava.system.class.loader=class 参数设置。该应用程序使用 RMI。在 eclipse 中一切正常,但是如果我导出一个可运行
我在使用 BouncyCaSTLe 1.59 进行签名/veryfing CADES 签名时遇到问题。我必须添加 messageDigest 属性,但是当我添加它时,我的程序失败了。 这是我的代码:
我是一名优秀的程序员,十分优秀!