您可以将文件 SHA1 散列到一定长度吗
Can you SHA1 hash a file to a certain length
我需要比较两个文件。一个文件可能比另一个长,我需要检查较长文件是否包含较短文件的所有数据。
我可以像这样对两者进行二进制比较:
function compareFiles($file_a, $file_b){
if (filesize($file_a) > filesize($file_b)){
$fp_a = fopen($file_b, 'rb');
$fp_b = fopen($file_a, 'rb');
} else { // filesize($file_b) > filesize($file_a)
$fp_a = fopen($file_a, 'rb');
$fp_b = fopen($file_b, 'rb');
}
while (($b = fread($fp_a, 4096)) !== false){
$b_b = fread($fp_b, 4096);
if ($b !== $b_b){
fclose($fp_a);
fclose($fp_b);
return false;
}
}
fclose($fp_a);
fclose($fp_b);
return true;
}
但这会很慢。作为替代方案,我可以将较小文件的 SHA1 哈希值与较大文件的 SHA1 哈希值进行比较,直到达到较小文件的大小为止,如下所示:
function compareFiles($file_a, $file_b){
$tmpfile = '/dev/shm/tmp_file_copy.bin';
if (filesize($file_a) > filesize($file_b)){
$readfromfile = $file_b;
$bytes_to_copy = filesize($file_b);
} else {
$readfromfile = $file_a
$bytes_to_copy = filesize($file_a);
}
$readfile = fopen($readfromfile, 'rb');
$writefile = fopen($tmpfile, 'wb');
while (!feof($readfile) && $bytes_to_copy> 0) {
if ($bytes_to_copy <= 8192) {
$contents = fread($readfile, $bytes_to_copy);
$bytes_to_copy = 0;
} else {
$contents = fread($readfile, 8192);
$bytes_to_copy =- 8192;
}
fwrite($writefile, $contents);
}
fclose($writefile);
fclose($readfile);
$result = sha1_file($readfromfile = $file_a ? $file_b : $file_a) === sha1_file($tmpfile);
unlink($tmpfile);
return $result;
}
但我担心这也会很慢,因为它涉及很多 I/O(到 /dev/shm)。
简而言之,我正在寻找更好的方法...
对于你的情况,逐字节是最好的方法。它只比较两个文件的前 x 个字节,如果它们不同则停止。哈希函数必须处理文件中的所有字节。那不是更慢吗?
在这种情况下散列文件只会更慢。考虑以下情况。
文件A.txt
内容:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
文件B.txt
内容:
AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB
注意 A.txt
一共 40 个字符,比 B.txt
30 个字符长 10 个字符
我们需要对每个文件执行多少 I/O 操作才能确定 A.txt
是否包含所有 B.txt
? 40字节? 30字节?不,答案只有 20 个字节,因为这是两个文件共享的共同点。您一次流式传输每个文件一个字节(或字节块),并在进行时比较它们。这种比较的结果如下所示:
A.txt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
B.txt: AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB
Stream ---------------------^
Result ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓X
然后你就停下来了。为什么要比较其余的?
如果对两个文件进行哈希处理,则必须将全部内容都存储在内存中才能计算哈希值。即使您在将它们流式传输到内存中时将它们分块散列,您认为哪个更快:比较每个文件中的每个字节或散列块?比较的复杂度为 O(number of bytes)
而 SHA-1 哈希算法的复杂度由 RFC 3174.
指定
我需要比较两个文件。一个文件可能比另一个长,我需要检查较长文件是否包含较短文件的所有数据。 我可以像这样对两者进行二进制比较:
function compareFiles($file_a, $file_b){
if (filesize($file_a) > filesize($file_b)){
$fp_a = fopen($file_b, 'rb');
$fp_b = fopen($file_a, 'rb');
} else { // filesize($file_b) > filesize($file_a)
$fp_a = fopen($file_a, 'rb');
$fp_b = fopen($file_b, 'rb');
}
while (($b = fread($fp_a, 4096)) !== false){
$b_b = fread($fp_b, 4096);
if ($b !== $b_b){
fclose($fp_a);
fclose($fp_b);
return false;
}
}
fclose($fp_a);
fclose($fp_b);
return true;
}
但这会很慢。作为替代方案,我可以将较小文件的 SHA1 哈希值与较大文件的 SHA1 哈希值进行比较,直到达到较小文件的大小为止,如下所示:
function compareFiles($file_a, $file_b){
$tmpfile = '/dev/shm/tmp_file_copy.bin';
if (filesize($file_a) > filesize($file_b)){
$readfromfile = $file_b;
$bytes_to_copy = filesize($file_b);
} else {
$readfromfile = $file_a
$bytes_to_copy = filesize($file_a);
}
$readfile = fopen($readfromfile, 'rb');
$writefile = fopen($tmpfile, 'wb');
while (!feof($readfile) && $bytes_to_copy> 0) {
if ($bytes_to_copy <= 8192) {
$contents = fread($readfile, $bytes_to_copy);
$bytes_to_copy = 0;
} else {
$contents = fread($readfile, 8192);
$bytes_to_copy =- 8192;
}
fwrite($writefile, $contents);
}
fclose($writefile);
fclose($readfile);
$result = sha1_file($readfromfile = $file_a ? $file_b : $file_a) === sha1_file($tmpfile);
unlink($tmpfile);
return $result;
}
但我担心这也会很慢,因为它涉及很多 I/O(到 /dev/shm)。
简而言之,我正在寻找更好的方法...
对于你的情况,逐字节是最好的方法。它只比较两个文件的前 x 个字节,如果它们不同则停止。哈希函数必须处理文件中的所有字节。那不是更慢吗?
在这种情况下散列文件只会更慢。考虑以下情况。
文件A.txt
内容:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
文件B.txt
内容:
AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB
注意 A.txt
一共 40 个字符,比 B.txt
30 个字符长 10 个字符
我们需要对每个文件执行多少 I/O 操作才能确定 A.txt
是否包含所有 B.txt
? 40字节? 30字节?不,答案只有 20 个字节,因为这是两个文件共享的共同点。您一次流式传输每个文件一个字节(或字节块),并在进行时比较它们。这种比较的结果如下所示:
A.txt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
B.txt: AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB
Stream ---------------------^
Result ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓X
然后你就停下来了。为什么要比较其余的?
如果对两个文件进行哈希处理,则必须将全部内容都存储在内存中才能计算哈希值。即使您在将它们流式传输到内存中时将它们分块散列,您认为哪个更快:比较每个文件中的每个字节或散列块?比较的复杂度为 O(number of bytes)
而 SHA-1 哈希算法的复杂度由 RFC 3174.