34 \ December 2018 \ http://www.phparch.com
Security Corner
Adventures in Hashing
Eric Mann
Last month, the PHP community had the opportunity to come together for the
excellent php[world] conference in Washington, D.C. As part of the event, we held
a hackathon to work through some of the challenges posed by Cryptopals^1. Some
of the cryptographic primitives we discussed were hashes, and it’s useful to take a
more in-depth look at what they are and how to use them in PHP.
1 Cryptopals: https://cryptopals.com
2 dynamic CDN: https://github.com/ericmann/dynamic-cdn
3 crc32: http://php.net/function.crc32
4 error-detection code: https://phpa.me/wikip-crc
Most developers equate hashing with password protection
as that’s usually the first and sometimes only encounter we
have with hashing algorithms. Hashing takes a plaintext input
and computes a deterministic—meaning the same input
string will always result in the same fixed length hash—but
seemingly random output. One advantage of hashing is the
obfuscation of input values. It’s this feature of hashing algo-
rithms we rely upon when protecting user passwords stored
in the database.
Hashed passwords in a database should always be paired
(and hashed) with a random salt. Since a hash function
will always produce the same output given a static input,
the presence of a random salt helps make two hashes of
the same plaintext password produce a different output
when two or more users use the same password.
Another prime advantage of hashing algorithms is the
magnification of differences between similar inputs. For
example, the SHA265 hash of adventure is:
47360b8c5f58c5ba04c8ce848545342c0490cfab23ce9f50e16e40b1df254ef8
The hash of Adventure is:
9041de6d46d70592cc5370cd1aa075ad2284581447ee4b408100afb3e1bd7024
Though the two input strings are very similar, the outputs
of the hashing function are very different. A change of just
one character in the input string might not be caught at first
glance—but the resulting difference in the hash output is
immediately apparent.
Many PHP applications use both of these features of hash-
ing algorithms. Obfuscation through hashing helps protect
passwords and other private information; it allows for the
comparison of sensitive data without leaking the actual values
of that data. Converting similar input strings to wildly differ-
ent outputs helps an application to separate and distribute
data into different buckets—this usually happens under the
hood, but can play a role in userland for some applications
as well.
Let’s look at some hashing functions and how to use them
in PHP.
Checksums
One of the more popular tools I’ve built is a dynamic CDN^2
plugin for WordPress. The plugin is a fork of earlier work.
Both help WordPress leverage an external CDN to offload
media hosting to a server more purpose-built for the task.
Often the CDN server is a collection of servers with similar
domains—cdn1.domain.com, cdn2.domain.com, and so on.
Each of the multiple domains is capable of serving up any
media file. In a browser world, however, we want to ensure the
same one always serves any particular item of media. Doing
so helps the browser properly cache the file and prevent
requesting the same one from each of the CDN servers.
As I built this tool, I needed a way to deterministically
identify the individual CDN server hosting an image without
keeping track of any form of state in a database. The easiest
way for me to do so involved a hash.
The crc32^3 function in PHP calculates an integer value from
a given string. It’s a function typically used to compute an
error-detection code^4 - –a “checksum”—that can be used to
detect changes in the input data. The value for my CDN utility
was the deterministic output of the function.
PHP’s crc32 would convert the same input string (a path
to a source media file) to the same integer checksum. I could
then compute a modulus by dividing this integer by the total
number of CDN domains in the system to determine which
CDN domain I should use for that file.
For example, 1002118588 is the crc32 checksum of the
following resource URL (all on one line):
https://www.phparch.com/wp-content/uploads/2017/12/
owasp-cover-3d-768x960.png