0

Here's my problem with PHP: For E-payment integration with Postfinance, I need to verify the data send and received with a SHA-256 hash of all the fields, with a secret key between each one.

How can you be sure that the input string will be in UTF-8 just before the hashing?

The command utf8_encode() is used on the input string, and if I check with mb_check_encoding(), it's okay. I have the good response, and if I use mb_detect_encoding(), the response is "ASCII".

$pf_post = array();

$pf_post['AMOUNT'] = 100;
$pf_post['CURRENCY'] = "CHF";
$pf_post['ORDERID'] = 101;
$pf_post['TITLE'] = "Paiement";

$pf_key = "mytestkey";

foreach (array_keys($pf_post) as $lakey)
{
    $pf_string .= strtoupper($lakey) . "=" . strval($pf_post[$lakey]) . $pf_key;
}

$pf_string = utf8_encode($pf_string);
$pf_sign = hash('sha256',$pf_string);

if (mb_check_encoding($pf_string, 'UTF-8')) {
    $debug .= "STRING => Détection UTF8 OK !<br>";
}
else {
    $debug .= "STRING => Détection UTF8 !!! ERREUR !!!<br>";
}

if (mb_check_encoding($pf_sign, 'UTF-8')) {
    $debug .= "HASH => Détection UTF8 OK !<br>";
}
else {
    $debug .= "HASH => Détection UTF8 !!! ERREUR !!!<br>";
}

$debug .= "String Format: " . mb_detect_encoding($pf_string) .
          ", Hash Format: " . mb_detect_encoding($pf_sign) . "<br>";

And here's the debug:

STRING => Détection UTF8 OK !
HASH => Détection UTF8 OK !
String Format : ASCII, Hash Format : ASCII

If I use only digits in the fields, it will be okay ... if I use letters, it will be not every time okay ... and if use letters with accent ... it's wrong anytime!

In HTML header, I have:

<meta charset="utf-8"/>

How can I fix this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Swiss GeckO
  • 11
  • 1
  • 3
  • Hi! Have you tried this? https://stackoverflow.com/a/1037368/1461181 – odan Aug 11 '17 at 08:06
  • _“the command utf8_encode() is used on the input string”_ - why, is it not UTF-8 already? We are talking about form data here, right? Your page is in UTF-8 already, so how did you manage to get form data send _not_ as UTF-8 in the first place? – CBroe Aug 11 '17 at 09:01
  • Or are you just talking about the `$pf_post` data here? If that is not UTF-8 already, it means you did not save your script file itself as UTF-8 - so _that_ would be the thing you need to correct, and not mess with encodings at runtime ... – CBroe Aug 11 '17 at 09:03
  • `utf8_encode()` == is your input string sure to be ***only*** `ISO-8859-1` type? – Martin Aug 11 '17 at 12:17
  • Thank for your help !!! – Swiss GeckO Aug 12 '17 at 13:11

2 Answers2

0

Here are some examples:

$str = "éóùùééééè"; // Will output 'éóùùééééè'
$strr = utf8_encode($str); // Will output 'éóùùééééè'

If you apply to an UTF-8 string, utf8_encode() will return a garbled UTF-8 output as shown in the example.

To ensure that you are using UTF-8, at the top of every script use mb_internal_encoding('UTF-8') and you can use this forceutf8 class.

<?php
    // Tell PHP that we're using UTF-8 strings until the end of the script
    mb_internal_encoding('UTF-8');

    include('Encoding.php'); // The class from GitHub

    // Same strings
    $str = 'éóùùééééè';
    $str1 = 'éóùùééééè'; //garbled UTF8 of éóùùééééè

    // Force input to UTF-8
    use \ForceUTF8\Encoding;
    echo Encoding::fixUTF8($str).'</br>'; // Will output éóùùééééè
    echo Encoding::fixUTF8($str1).'</br>'; // Will output éóùùééééè

    $str3 = Encoding::fixUTF8($str);
    $str4 = Encoding::fixUTF8($str1);


    // Then hash
    $hash1 = hash('sha256', $str3);
    $hash1 = hash('sha256', $str4);

    echo $hash1; // Will output 45b8151559a5136d58f85ebf51c24f26c47e51f4a89fe2962c8626e99ad64786
    echo $hash2; // Will output 45b8151559a5136d58f85ebf51c24f26c47e51f4a89fe2962c8626e99ad64786

    // mb_detect_encoding will always output ASCII
    echo  mb_detect_encoding($hash1). '</br>'; // Will output ASCII
    echo  mb_detect_encoding($hash1); //// Will output ASCII

And at the browser level you need:

<meta charset="UTF-8">
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Michael GEDION
  • 879
  • 8
  • 16
0

You should not encode the values to UTF-8 twice. I would suggest to encode only if really necessary. Example:

if (!mb_check_encoding($pf_string, 'UTF-8')) {
    $pf_string = mb_convert_encoding($pf_string, 'UTF-8');
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
odan
  • 4,757
  • 5
  • 20
  • 49