Переписать хеш-функцию с php на java - другой результат - PullRequest
0 голосов
/ 12 января 2019

Мне нужно переписать функцию хеширования с php на java.

Я переписал функции, используемые в php-коде, в java и основной алгоритм. Это проблема, потому что результат в Java отличается от php.

PHP код:

$salt = "ddedca658b683479cc779fc31def17c79e73dcd4b842ec335d49696cb64d8fda";
function calculateControlData($salt, $controlString)
{
    $hexLenght = strlen($salt);
    $saltBin = "";
    for ($x = 1; $x <= $hexLenght/2; $x++)
    {
        $saltBin .= (packH("H*", substr($salt,2 * $x - 2,2)));
    }
    return hashSHA256("sha256", $controlString.$saltBin);
}

версия для отладки:

function calculateControlData($salt, $controlString)
{
                    $hexLenght = strlen($salt);

                    $saltBin = "";
                    for ($x = 1; $x <= $hexLenght/2; $x++)
                    {
                            $magicChar=(pack("H*", substr($salt,2 * $x - 2,2)));

                            echo $x.' -> '.substr($salt,2 * $x - 2,2).' -> ';
                            echo $magicChar.' -> ';
                            echo ord($magicChar).' | ';

                            $saltBin .= $magicChar;                                
                    }


                    echo '<br>saltBin = '.$saltBin.'<br>';
                    echo '$controlString.$saltBin = '.$controlString.$saltBin.'<br>';
                    echo 'controlData = '.hash("sha256", $controlString.$saltBin).'<br>';

                    echo 'SHA256 for T3$T123456 = '.hash("sha256", 'T3$T123456').'<br><br>';

                    return hash("sha256", $controlString.$saltBin);
}

результат:

1 -> dd -> � -> 221 | 2 -> ed -> � -> 237 | 3 -> ca -> � -> 202 | 4 -> 65 -> e -> 101 | 5 -> 8b -> � -> 139 | 6 -> 68 -> h -> 104 | 7 -> 34 -> 4 -> 52 | 8 -> 79 -> y -> 121 | 9 -> cc -> � -> 204 | 10 -> 77 -> w -> 119 | 11 -> 9f -> � -> 159 | 12 -> c3 -> � -> 195 | 13 -> 1d ->  -> 29 | 14 -> ef -> � -> 239 | 15 -> 17 ->  -> 23 | 16 -> c7 -> � -> 199 | 17 -> 9e -> � -> 158 | 18 -> 73 -> s -> 115 | 19 -> dc -> � -> 220 | 20 -> d4 -> � -> 212 | 21 -> b8 -> � -> 184 | 22 -> 42 -> B -> 66 | 23 -> ec -> � -> 236 | 24 -> 33 -> 3 -> 51 | 25 -> 5d -> ] -> 93 | 26 -> 49 -> I -> 73 | 27 -> 69 -> i -> 105 | 28 -> 6c -> l -> 108 | 29 -> b6 -> � -> 182 | 30 -> 4d -> M -> 77 | 31 -> 8f -> � -> 143 | 32 -> da -> � -> 218 | 

saltBin = ���e�h4y�w���Ǟs�ԸB�3]Iil�M��

$controlString.$saltBin = pos_id=74294910&order_id=REZ_1234&session_id=999&amount=100¤cy=PLN&test=Y&language=PL&client_ip=127.0.0.1&email=a.lacek@testmail.pl&ba_firstname=Aleksander&ba_lastname=Lacek���e�h4y�w���Ǟs�ԸB�3]Iil�M��

controlData = f27b95a152da64c27958d16e6a48cd98ddfefaf49a8e28552cc67388cf36c353

SHA256 for T3$T123456 = b11866fcf57e9419c747de9f23380bb1c6b23a9b189cc2ef14840bf40ce19a8f

Код в Java:

final String SALT = "ddedca658b683479cc779fc31def17c79e73dcd4b842ec335d49696cb64d8fda";

private String calculateControlData(String request)
        throws UnsupportedEncodingException, NoSuchAlgorithmException {

    System.out.println("request: " + request);

    int hexLenght = SALT.length();
    String saltBin = "";
    for (int x = 1; x <= hexLenght / 2; x++) {
        int beginIndex = 2 * x - 2;
        String literki = SALT.substring(beginIndex, beginIndex + 2);
        char packLiterki = packH(literki); // (packH("H*", substr($salt,2 * $x - 2,2)));
        saltBin += packLiterki;

        System.out.println(x + ": " + literki + " -> " + packLiterki + " -> " + (int) packLiterki);
    }
    System.out.println("saltBin = " + saltBin);
    String stringForHash = request + saltBin;
    System.out.println("stringForHash = " + stringForHash);
    String hashedString = hashSHA256(stringForHash);
    System.out.println("hashedString = "+hashedString);
    return hashedString;
}

private char packH(String hex) {
    String input = hex.length() % 2 == 0 ? hex : hex + "0";
    StringBuilder output = new StringBuilder();
    for (int i = 0; i < input.length(); i += 2) {
        String str = input.substring(i, i + 2);
        output.append((char) Integer.parseInt(str, 16));
    }
    return output.toString().charAt(0);
}

private String hashSHA256(String originalString) throws NoSuchAlgorithmException {

    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    byte[] encodedhash = digest.digest(
            originalString.getBytes(StandardCharsets.UTF_8));

    StringBuffer hexString = new StringBuffer();
    for (int i = 0; i < encodedhash.length; i++) {
        String hex = Integer.toHexString(0xff & encodedhash[i]);
        if (hex.length() == 1) hexString.append('0');
        hexString.append(hex);
    }
    return hexString.toString();
}

результат:

request: pos_id=74294910&order_id=REZ_1234&session_id=999&amount=100&currency=PLN&test=Y&language=PL&client_ip=127.0.0.1&email=a.lacek@testmail.pl&ba_firstname=Aleksander&ba_lastname=Lacek

1: dd -> Ý -> 221
2: ed -> í -> 237
3: ca -> Ê -> 202
4: 65 -> e -> 101
5: 8b ->  -> 139
6: 68 -> h -> 104
7: 34 -> 4 -> 52
8: 79 -> y -> 121
9: cc -> Ì -> 204
10: 77 -> w -> 119
11: 9f ->  -> 159
12: c3 -> Ã -> 195
13: 1d ->  -> 29
14: ef -> ï -> 239
15: 17 ->  -> 23
16: c7 -> Ç -> 199
17: 9e ->  -> 158
18: 73 -> s -> 115
19: dc -> Ü -> 220
20: d4 -> Ô -> 212
21: b8 -> ¸ -> 184
22: 42 -> B -> 66
23: ec -> ì -> 236
24: 33 -> 3 -> 51
25: 5d -> ] -> 93
26: 49 -> I -> 73
27: 69 -> i -> 105
28: 6c -> l -> 108
29: b6 -> ¶ -> 182
30: 4d -> M -> 77
31: 8f ->  -> 143
32: da -> Ú -> 218

saltBin = ÝíÊeh4yÌwÃïÇsÜÔ¸Bì3]Iil¶MÚ

stringForHash = pos_id=74294910&order_id=REZ_1234&session_id=999&amount=100&currency=PLN&test=Y&language=PL&client_ip=127.0.0.1&email=a.lacek@testmail.pl&ba_firstname=Aleksander&ba_lastname=LacekÝíÊeh4yÌwÃïÇsÜÔ¸Bì3]Iil¶MÚ

hashedString = 6d47c2e1688f87bf7c65a1a2be6a9329611a381dafd0d8cfefcaca57e29e5eb6
controlData: 6d47c2e1688f87bf7c65a1a2be6a9329611a381dafd0d8cfefcaca57e29e5eb6

SHA-256 for T3$T123456: b11866fcf57e9419c747de9f23380bb1c6b23a9b189cc2ef14840bf40ce19a8f

Я обнаружил, что значения ord, сгенерированные как packH в java, так и pack ("H *", $ str) в результатах php, одинаковы, но строка saltBin выглядит иначе. Я думаю, что есть проблема, потому что hashSHA256 в Java и hashSHA256 ("sha256", $ str) в php дают тот же результат. Как это решить ??

1 Ответ

0 голосов
/ 12 января 2019
  • Операция string в Java отличается от php
  • Некоторая операция в коде Java неверна.
  • Следующий код является решением (проходит тестирование):
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Main {

    public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        String s = new Main().calculateControlData("pos_id=74294910&order_id=REZ_1234&session_id=999&amount=100&currency=PLN&test=Y&language=PL&client_ip=127.0.0.1&email=a.lacek@testmail.pl&ba_firstname=Aleksander&ba_lastname=Lacek");
        System.out.println(s);
    }

    final String SALT = "ddedca658b683479cc779fc31def17c79e73dcd4b842ec335d49696cb64d8fda";

    private String calculateControlData(String request)
            throws NoSuchAlgorithmException, UnsupportedEncodingException {

        int hexLenght = SALT.length();
        byte[] saltBinBytes = new byte[32];
        for (int x = 1; x <= hexLenght / 2; x++) {
            int beginIndex = 2 * x - 2;
            String literki = SALT.substring(beginIndex, beginIndex + 2);
            char packLiterki = packH(literki); // (packH("H*", substr($salt,2 * $x - 2,2)));

//            saltBin += packLiterki;
            // 1. this should use byte array to save the result
            saltBinBytes[x - 1] = ((byte) packLiterki);
        }

        // 2. concat bytes of two string
        byte[] requestBytes = request.getBytes(StandardCharsets.UTF_8);
        byte[] bytes = new byte[requestBytes.length + saltBinBytes.length];
        System.arraycopy(requestBytes, 0, bytes, 0, requestBytes.length);
        System.arraycopy(saltBinBytes, 0, bytes, requestBytes.length, saltBinBytes.length);

        return hashSHA256(bytes);
    }

    private char packH(String hex) {
        String input = hex.length() % 2 == 0 ? hex : hex + "0";
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < input.length(); i += 2) {
            String str = input.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString().charAt(0);
    }

    // 3. arguments changes to byte array
    private String hashSHA256(byte[] bytes) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] encodedhash = digest.digest(bytes);

        StringBuffer hexString = new StringBuffer();
        for (byte b : encodedhash) {
            // 4. convert sha256 result to compatible php
            hexString.append(String.format("%02x", b));
        }

        return hexString.toString();
    }
}

Вывод f27b95a152da64c27958d16e6a48cd98ddfefaf49a8e28552cc67388cf36c353, такой же как php

  • php код (убрать эхо)
<?php

$salt = "ddedca658b683479cc779fc31def17c79e73dcd4b842ec335d49696cb64d8fda";

function calculateControlData($salt, $controlString)
{
    $hexLenght = strlen($salt);

    $saltBin = "";
    for ($x = 1; $x <= $hexLenght/2; $x++)
    {
        $magicChar=(pack("H*", substr($salt,2 * $x - 2,2)));
        $saltBin .= $magicChar;
    }

    return hash("sha256", $controlString.$saltBin);
}

echo  calculateControlData($salt, 'pos_id=74294910&order_id=REZ_1234&session_id=999&amount=100&currency=PLN&test=Y&language=PL&client_ip=127.0.0.1&email=a.lacek@testmail.pl&ba_firstname=Aleksander&ba_lastname=Lacek');

вывод также f27b95a152da64c27958d16e6a48cd98ddfefaf49a8e28552cc67388cf36c353

...