title: Hash to create unique URL so that it is difficul to guess valid URLs in lieu of authentication
body: <p>I'm considering writing a webpage which provides a feedback form for customers.<br>
  I would like customers to be able to access this form with a unique URL for any particular order; a simple example would be in the format of <a href="http://www.example.com/feedback/012345" rel="noreferrer">http://www.example.com/feedback/012345</a>.</p>
  
  <p><em>Sidenote: I am already familiar with URL rewriting. The creation / redirection of the URL in a given language or on a given server is outside of the scope of this question</em></p>
  
  <p><strong>It is unacceptable for the customer to have to authenticate</strong> (or, for that matter, even possess an account) in order to access the feedback form. But, out of concern for statistical correctness, I am not satisfied with the obvious solution above of example.com/feedback/[order_id]. This allows for anybody to change the ID in the URL and access feedback for another order.</p>
  
  <p>On the other hand, I would ideally like these URLs to be able to be typed in from a printout such as a receipt, so <strong>providing a long hash like on a lot of "reset password" links is not a valid option</strong>.</p>
  
  <p><strong>Based on this, I have the following criteria :</strong></p>
  
  <ol>
  <li>A unique URL should exist for every order</li>
  <li>This URL should be relatively human typeable, for now take this to mean "short"</li>
  <li>It should not be possible to change characters in the URL and access other orders (within reasonable realms of probability)</li>
  </ol>
  
  <p>My line of thinking is that I should put two pieces of data in the URL. There's a lot of human readable data available on customer records which could help with this, for example customer ID, contact phone number for order, surname...  While this removes the ability to change a digit or two, I don't see it markedly improving the "guessability" of a given URL to a bored attacker.</p>
  
  <p>Taking the trivial example of /feedback/[surname]/[id], you can simple dictionary attack the page to receive a set of valid URLs:</p>
  
  <pre><code>for x in range(00000,99999):
      for name in ["jones","smith", ....]:
          url = "http://www.example.com/feedback/"+name+"/"+x
          if exists(url):
              print(url)
  </code></pre>
  
  <p><br><br>
  The next thing I considered, with services like tinyurl in mind, is hashing the ID number and providing a URL in the form of /feedback/[hash]/[id]<br>
  <em>I've since done some research and learned that URL shortening services actually probably use auto-increment ID records rather than an actual mathematical hash. This method is probably not useful</em></p>
  
  <p>If an actual hash function is used, <strong>it is important that the hash isn't obviously derived from the ID number</strong>. Providing a URL like /feedback/trpxq/53192 would be useless, because after seeing one or two of them you can trivially pull the previous record: /feedback/trpxp/53191</p>
  
  <p>I was thinking then, that it would maybe be helpful if the hash included a salt so that, even with the knowledge of what hash function was used, it will not be possible to hash any old valid order ID and bring up a valid URL.</p>
  
  <p>So, finally, here's the actual question:</p>
  
  <p><strong>What function would be best used to create a short, non-obvious, relatively unique alphanumeric representation of a hash based on a 7-10 digit integer ID and an arbitrary salt?</strong></p>
  
  <p>This isn't a URL shortening problem per se, so I would be satisfied if the hash part is the same length as the ID part: reduction to 10 alphanumeric characters is acceptable.</p>
  
  <p>In addition, the hash does not necessarily need to be calculated every time the URL is accessed. It's possible to calculate it either when the order record is created, or when the page is first accessed for that order ID. This means the hash function doesn't strictly have to be fast.</p>
  
  <p>Although there's the potential to essentially create a hash table for lookup purposes, this problem doesn't have the same restraints as a hash table: lookup is done based on an already unique value, so conflict resolution isn't strictly necessary provided it is sufficiently difficult to find another record with the same hash for a given hash. </p>
  
  <p><br><br>
  We're now well and truly outside of the practical realms of what needs to be done to secure a feedback form - this data isn't actually that important to protect - but humour me, this is an interesting problem and I'd like to know if there's a good solution which maximizes both security and readability.</p>