title: Verifying that two files are identical using pure PHP?
body: <p>TL;DR: I have an CMS system that stores attachments (opaque files) using SHA-1 of the file contents as the filename. How to verify if uploaded file really matches one in the storage, given that I already know that SHA-1 hash matches for both files? I'd like to have high performance.</p>
  
  <p><strong>Long version:</strong></p>
  
  <p>When an user uploads a new file to the system, I compute SHA-1 hash of the uploaded file contents and then check if a file with identical hash already exists in the storage backend. PHP puts the uploaded file in <code>/tmp</code> before my code gets to run and then I run <code>sha1sum</code> against the uploaded file to get SHA-1 hash of the file contents. I then compute fanout from the computed SHA-1 hash and decide storage directory under NFS mounted directory hierarchy. (For example, if the SHA-1 hash for a file contents is <code>37aefc1e145992f2cc16fabadcfe23eede5fb094</code> the permanent file name is <code>/nfs/data/files/37/ae/fc1e145992f2cc16fabadcfe23eede5fb094</code>.) In addition to saving the actual file contents, I <code>INSERT</code> a new line into a SQL database for the user submitted meta data (e.g. <code>Content-Type</code>, original filename, datestamp, etc).</p>
  
  <p>The corner case I'm currently figuring out is the case where a new uploaded file has SHA-1 hash that matches existing hash in the storage backend. I know that the changes for this happening by accident are astronomically low, but I'd like to be sure. (For on purpose case, see <a href="https://shattered.io/" rel="noreferrer">https://shattered.io/</a>)</p>
  
  <p><strong>Given two filenames <code>$file_a</code> and <code>$file_b</code>, how to quickly check if both files have identical contents?</strong> Assume that files are too big to be loaded into memory. With Python, I'd use <code>filecmp.cmp()</code> but PHP does not seem to have anything similar. I know that this can be done with <code>fread()</code> and aborting if a non-matching byte is found, but I'd rather not write that code.</p>