0

I am trying to write verification code in PhP following these steps...

The verification code is calculated by:

  1. Verification code = integer(SHA256(the hash)[-2:-1]) mod 10000
  2. Calculate SHA256 from the hash, extract 2 rightmost bytes from the result, interpret them as a big-endian unsigned integer and take the last 4 digits in decimal form for display. SHA256 is always used here.
  3. Please mind that hash is a real hash byte value, not the Base64 form or the hexadecimal representation.

So far I have this code, but it's not working like I was hoping for:

function calculateVcode($hashString) {
  $md = hash_init('sha256');
  $hash = base64_decode($hashString);
  hash_update($md, $hash);
  $hash = hash_final($md, true);
  $last = substr($hash, -2);
  $code = bindec($last);
  return substr(strval($code), -4);
}

$hashString = "Demo string for Authentication";
$md5Hash = md5($hashString);
$result = calculateVcode($md5Hash);`

Any ideas how to get this working or am I totally on the wrong path ?

Result could be like: Text used to generate a hash string “Auðkenni APP Authentication”

Hash string generated n/kRNhXaZ2jFKv8KlQX7ydgedXUmVy8b2O4xNq2ZxHteG7wOvCa0Kg3rY1JLOrOBXYQm+z2FRVwIv47w8gUb5g==

Verification code calculated from the hash 4141

1
  • Why do you use base64_decode() on the result from md5()? Commented May 4, 2024 at 16:34

1 Answer 1

0

What you need for proper SHA-256 hashing is the raw binary data that MD5 represents, not the encoded or string version of it. If you start with an MD5 hash string, you should convert this string back to its binary format if it's hex-encoded, or ensure that you're dealing with the binary data directly.

Also the way you're converting the last 2 bytes to an integer isn't quite right. The bindec() function is not for converting binary data directly to integer, as it interprets a binary string, not raw bytes.

Once these are corrected you should expected results:

function calculateVcode($hashString) {
    // Assume $hashString is already a proper byte sequence
    $hash = hash('sha256', $hashString, true); // true for raw binary output
    $lastTwoBytes = substr($hash, -2); // Get the last 2 bytes
    $value = unpack("n", $lastTwoBytes); // Unpack as a big-endian ushort (16-bit int)
    $code = $value[1] % 10000; // get last 4 digits
    return $code;
}

$originalText = "Auðkenni APP Authentication";
$hashString = base64_decode("n/kRNhXaZ2jFKv8KlQX7ydgedXUmVy8b2O4xNq2ZxHteG7wOvCa0Kg3rY1JLOrOBXYQm+z2FRVwIv47w8gUb5g==");
$result = calculateVcode($hashString);
echo "Verification code: " . $result . "\n";

BTW: Your method to take the last 4 digits might result in errors if the converted integer is less than 4 digits long.


what is the best way to create the raw hash string ?

I'd generate a raw (in its binary form) SHA-512 hash of your data. Then encode it into Base64, which is necessary to transmit or store the hash in a text-friendly format. When you need to use this hash for further processing (like calculating your verification code), you'll decode it from Base64 back to its original raw binary form:

function createBase64EncodedSHA512(string $input): string {
    $rawHash = hash('sha512', $input, true);
    return base64_encode($rawHash);
}

function calculateVcodeFromBase64SHA512(string $base64EncodedHash): int {
    $hashBytes = base64_decode($base64EncodedHash);
    $hash = hash('sha256', $hashBytes, true);
    $lastTwoBytes = substr($hash, -2);
    $value = unpack("n", $lastTwoBytes);
    $code = $value[1] % 10000;
    return $code;
}

Usage example

$inputData = "Your data here";
$base64SHA512 = createBase64EncodedSHA512($inputData);
$verificationCode = calculateVcodeFromBase64SHA512($base64SHA512);
echo "Verification Code: " . $verificationCode . "\n";
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Marcin, great input and I can see my mistakes. But regarding the input to the function, what is the best way to create the raw hash string ? The instructions say: You’ll need to provide the hash string to use. That’s how you can calculate the verification code at your side to display at your website for your user to see. The hash string should be of type SHA512 Please mind that the hash string should be in Base64 format.
Thanks Marcin ! Absolutely brilliant, you have solved this puzzle for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.