Working with Binary Data and Cryptographic Hashing in PHP
Working with binary data and cryptographic hashing in PHP is important when developing applications that handle files, digital signatures, API authentication, data integrity checks, tokens, and other security-sensitive operations.
PHP provides several built-in functions for working with bytes and binary-safe strings, including bin2hex(), hex2bin(), pack(), and unpack(). For cryptographic hashing, PHP provides functions such as hash(), hash_file(), hash_hmac(), and hash_equals().
Understanding the difference between binary data, hexadecimal representations, cryptographic hashes, HMACs, and password hashes can help developers avoid common security and data-processing mistakes.
Key Principle: Use the appropriate PHP function for the specific task. Cryptographic hashing, password hashing, encoding, and binary-data conversion solve different problems and should not be treated as interchangeable.
What Is Binary Data in PHP?
Binary data is data represented as a sequence of bytes. Images, PDFs, compressed files, encrypted data, and many network protocols contain binary data.
PHP strings are binary-safe, which means a string can contain arbitrary byte values. However, binary data is often difficult to display or store directly in text-based formats.
For example:
$data = "Hello GizDevCraft";
echo strlen($data);
The strlen() function returns the number of bytes in the string.
When dealing with binary data, developers commonly convert the bytes into a readable hexadecimal representation.
Converting Binary Data to Hexadecimal with bin2hex()
The bin2hex() function converts binary data into its hexadecimal representation.
$data = "Hello GizDevCraft";
$hex = bin2hex($data);
echo $hex;
Output:
48656c6c6f2047697a4465764372616674
Hexadecimal output is useful when debugging binary values, storing byte sequences in text-based systems, or displaying binary information in logs.
Keep in mind that hexadecimal encoding increases the size of the data because each byte is represented by two hexadecimal characters.
Converting Hexadecimal Back to Binary with hex2bin()
The hex2bin() function performs the reverse operation.
$hex = "48656c6c6f";
$data = hex2bin($hex);
echo $data;
Output:
Hello
This is useful when hexadecimal data needs to be converted back into its original binary representation.
You should also validate externally supplied hexadecimal data before processing it:
$hex = $_POST['data'] ?? '';
if (ctype_xdigit($hex) && strlen($hex) % 2 === 0) {
$binary = hex2bin($hex);
}
The even-length check is important because every byte requires exactly two hexadecimal characters.
Packing Data into Binary Format with pack()
PHP's pack() function converts values into a binary string according to a specified format.
For example:
$binary = pack('C*', 72, 101, 108, 108, 111);
echo $binary;
Output:
Hello
The C format represents unsigned characters.
pack() becomes particularly useful when working with binary protocols, file formats, network data, or applications that require a specific byte-level representation.
For example:
$binary = pack('n', 500);
echo bin2hex($binary);
Here, the n format packs the integer into a 16-bit unsigned value using big-endian byte order.
Reading Binary Data with unpack()
The unpack() function extracts values from a binary string according to a specified format.
$binary = pack('n', 500);
$result = unpack('nvalue', $binary);
echo $result['value'];
Output:
500
Together, pack() and unpack() are useful when PHP applications need to communicate with systems that use structured binary data.
Generating Cryptographic Hashes with hash()
A cryptographic hash converts input data into a fixed-length digest.
PHP provides the hash() function for generating hashes using supported algorithms.
For example, generating a SHA-256 hash:
$data = "Hello GizDevCraft";
$hash = hash('sha256', $data);
echo $hash;
The result is a hexadecimal string representing the SHA-256 digest.
A hash is designed to be one-way: you generally cannot recover the original input from the hash.
Choosing a Hash Algorithm
For modern integrity and security-related applications, SHA-256 and SHA-512 are commonly used cryptographic hash algorithms.
For example:
$data = "Important application data";
$sha256 = hash('sha256', $data);
$sha512 = hash('sha512', $data);
echo $sha256;
echo PHP_EOL;
echo $sha512;
Avoid using outdated algorithms such as MD5 or SHA-1 for security-sensitive purposes.
Returning Raw Binary Hash Output
By default, hash() returns a hexadecimal string. You can request the raw binary digest by passing true as the third argument.
$data = "Hello GizDevCraft";
$binaryHash = hash('sha256', $data, true);
echo bin2hex($binaryHash);
This can be useful when a hash needs to be combined with other binary data or processed as bytes.
The difference is important:
hash('sha256', $data);
returns a hexadecimal representation, while:
hash('sha256', $data, true);
returns the raw binary digest.
Hashing Files with hash_file()
When you need to calculate a hash for a file, PHP provides hash_file().
$file = __DIR__ . '/example.pdf';
$hash = hash_file('sha256', $file);
echo $hash;
File hashing is useful for checking whether a file has changed.
For example, an application could calculate the SHA-256 hash of a downloaded file and compare it with a trusted hash.
$expectedHash = '...';
$actualHash = hash_file('sha256', 'example.zip');
if (hash_equals($expectedHash, $actualHash)) {
echo "File integrity verified.";
} else {
echo "File verification failed.";
}
Secure Hash Comparison with hash_equals()
When comparing security-sensitive values such as hashes or HMAC signatures, PHP provides hash_equals().
$expected = hash('sha256', 'Hello GizDevCraft');
$received = hash('sha256', 'Hello GizDevCraft');
if (hash_equals($expected, $received)) {
echo "Values match.";
}
Using hash_equals() helps avoid timing-attack issues associated with ordinary string comparison in security-sensitive situations.
Do not use it as a replacement for generating a secure hash. It is specifically for comparing two values safely.
Creating HMAC Signatures with hash_hmac()
A normal hash does not prove that the data came from a trusted source. When authentication is required, an HMAC can be used.
PHP provides hash_hmac() for generating keyed hashes.
$message = 'Hello GizDevCraft';
$secret = 'my-secret-key';
$signature = hash_hmac('sha256', $message, $secret);
echo $signature;
The sender and receiver can use the same secret key to generate and verify the signature.
A simplified verification example:
$message = 'Hello GizDevCraft';
$secret = 'my-secret-key';
$receivedSignature = hash_hmac(
'sha256',
$message,
$secret
);
$expectedSignature = hash_hmac(
'sha256',
$message,
$secret
);
if (hash_equals($expectedSignature, $receivedSignature)) {
echo "Signature is valid.";
}
In a real application, the secret should never be hard-coded into source code. Store secrets securely using environment variables or an appropriate secrets-management system.
Cryptographic Hashing Is Not Password Hashing
One of the most important distinctions for PHP developers is that general-purpose cryptographic hashing should not be used directly for storing passwords.
Avoid this:
$passwordHash = hash('sha256', $password);
Passwords should be processed using PHP's password hashing API.
Use:
$passwordHash = password_hash(
$password,
PASSWORD_DEFAULT
);
Then verify the password with:
if (password_verify($password, $passwordHash)) {
echo "Password is correct.";
}
Password hashing functions are specifically designed for password storage and verification.
Binary Data vs Hexadecimal Data
It is useful to understand the difference between binary data and its hexadecimal representation.
For example:
$data = "ABC";
$hex = bin2hex($data);
echo $hex;
The original string contains three bytes, while its hexadecimal representation contains six characters:
ABC
414243
The hexadecimal form is easier for humans to inspect, but it is not the same representation as the original binary data.
You can convert it back:
$binary = hex2bin('414243');
echo $binary;
Output:
ABC
Common Developer Mistakes
1. Using MD5 or SHA-1 for security-sensitive operations
These algorithms are considered unsuitable for many modern security applications.
Use a modern cryptographic algorithm such as SHA-256 when a general-purpose cryptographic hash is required.
2. Using SHA-256 directly for passwords
A password hash needs to be deliberately expensive and resistant to password-cracking attacks.
Use:
password_hash($password, PASSWORD_DEFAULT);
and:
password_verify($password, $hash);
3. Confusing encoding with hashing
Hexadecimal encoding can be reversed:
hex2bin(bin2hex($data));
A cryptographic hash is designed to be one-way.
Encoding and hashing are therefore fundamentally different operations.
4. Treating hexadecimal strings as binary data
If an application receives:
48656c6c6f
that is a hexadecimal representation. Convert it with hex2bin() when the application actually needs the corresponding bytes.
5. Comparing security values with ordinary comparisons
For security-sensitive comparisons, use:
hash_equals($expected, $received);
instead of relying on ordinary string comparisons.
6. Hard-coding cryptographic secrets
Avoid placing API keys, HMAC secrets, or other credentials directly in application source code.
Use environment variables or a secure secret-management solution instead.
Complete PHP Example
The following example combines binary conversion, hashing, and secure comparison:
<?php
$data = "GizDevCraft PHP Tutorial";
// Convert text to hexadecimal.
$hex = bin2hex($data);
echo "Hexadecimal: " . $hex . PHP_EOL;
// Convert hexadecimal back to binary/text.
$decoded = hex2bin($hex);
echo "Decoded: " . $decoded . PHP_EOL;
// Generate SHA-256 hash.
$hash = hash('sha256', $data);
echo "SHA-256: " . $hash . PHP_EOL;
// Verify the hash.
$expectedHash = hash('sha256', 'GizDevCraft PHP Tutorial');
if (hash_equals($expectedHash, $hash)) {
echo "Hash verification successful.";
} else {
echo "Hash verification failed.";
}
This example demonstrates the distinction between binary conversion, hexadecimal encoding, cryptographic hashing, and secure comparison.
Performance Considerations
Hashing is generally efficient, but applications that process large files or large volumes of data should avoid unnecessary conversions.
For example, if an application only needs to calculate a file's SHA-256 digest, use:
$hash = hash_file('sha256', $file);
rather than loading the entire file into memory unnecessarily.
When processing binary data, also avoid repeatedly converting between binary and hexadecimal representations unless the conversion is actually required.
For high-volume applications, profile the operation and consider the amount of data being processed, memory usage, and the selected algorithm.
Security Best Practices
When working with binary data and cryptographic functions in PHP:
-
Use modern cryptographic algorithms for security-sensitive hashing.
-
Use
password_hash()for password storage. -
Use
password_verify()for password verification. -
Use
hash_equals()for security-sensitive comparisons. -
Use HMAC when message authentication with a shared secret is required.
-
Keep cryptographic secrets outside application source code.
-
Validate externally supplied hexadecimal data before calling
hex2bin(). -
Do not assume that hexadecimal encoding provides encryption.
-
Use
hash_file()for efficient file-integrity checks. -
Keep PHP and its cryptographic libraries updated.
Frequently Asked Questions
What is binary data in PHP?
Binary data is information represented as bytes. PHP strings are binary-safe, allowing them to contain arbitrary byte values. Binary data is commonly encountered when working with images, PDFs, compressed files, network protocols, and cryptographic operations.
What does bin2hex() do in PHP?
bin2hex() converts binary data into a hexadecimal string. It is commonly used when binary values need to be displayed, logged, or represented in a text-friendly format.
What does hex2bin() do in PHP?
hex2bin() converts a hexadecimal string back into its binary representation.
What is the difference between hash() and hash_hmac()?
hash() generates a cryptographic hash from input data, while hash_hmac() generates a keyed hash using a secret key. HMAC is useful when the application needs to authenticate a message using a shared secret.
Should I use SHA-256 to store passwords?
No. Do not use a general-purpose hash such as SHA-256 directly for password storage. Use PHP's password_hash() and verify passwords with password_verify().
Why should I use hash_equals()?
hash_equals() is designed for safely comparing security-sensitive strings, such as cryptographic hashes and HMAC signatures, in a way that helps reduce timing-attack risks.
Conclusion
Working with binary data and cryptographic hashing in PHP requires an understanding of both byte-level data handling and security principles.
Functions such as bin2hex(), hex2bin(), pack(), and unpack() make it possible to manipulate binary data, while hash(), hash_file(), and hash_hmac() provide cryptographic hashing capabilities. For security-sensitive comparisons, hash_equals() should be used, while passwords should be handled through password_hash() and password_verify().
The most important lesson is to choose the right tool for the job: encoding is not hashing, hashing is not encryption, and password hashing is different from general-purpose cryptographic hashing.
Discussion (0)
Sign in to join the discussion
Only registered developers with verified email addresses can leave comments.
No comments yet. Be the first to start the conversation!