OpenSSL :: HMA C .hexdigest PHP эквивалент не будет печатать тот же результат, что и ruby one - PullRequest
0 голосов
/ 17 января 2020

Это код ruby, который мне нужно преобразовать в PHP:

print OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 'hello', Base64.encode64('bonjour'))

Вывод:

62ac34e5d28563d6a50272d660805d1f8c791e41

Это мой PHP код:

echo hash_hmac('sha1', base64_encode('bonjour'), 'hello');

Вывод:

89ebf8bd3d92bf3283aa4c5f24072820258367e4

Я не могу найти способ 62ac34....

Я тоже пробовал:

echo hash_hmac('sha1', 'bonjour', 'hello'); // 1
echo hash_hmac('sha1', 'hello', 'bonjour'); // 2
echo hash_hmac('sha1', base64_encode('hello'), 'bonjour'); // 3
echo hash_hmac('sha1', 'hello', base64_encode('bonjour')); // 4
echo base64_encode(hash_hmac('sha1', 'hello', 'bonjour', TRUE)); //5

Что тоже не так. Вывод:

bed443484cc49c41c053a11dd15e44d4f79c524f // 1
16923f8d6e9afd345cf947fc963cad73aa12b76c // 2
8e5989976296c76f0462fe33c6bc2dec48bdcb5a // 3
ca237e79f77e6d9739db45fc5d162da3a4036639 // 4
FpI/jW6a/TRc+Uf8ljytc6oSt2w= // 5

Я в полном отчаянии.

РЕДАКТИРОВАТЬ

Ответ @Casper не полностью отвечает моим ожиданиям. В случае простой строки типа bonjour проблем нет. Но когда я добавляю более сложную строку, строку json или более длинную строку (> 60), появляются проблемы.

Прежде всего, следуя модулю Base64 Ruby :

encode64 (bin)

Возвращает версию bin64 в кодировке Base64. Этот метод соответствует RF C 2045. Переводы строк добавляются к каждые 60 закодированных символов.

Итак, чтобы иметь одинаковые закодированные в base64 данные в PHP, мне нужно вставить \n каждые 60 закодированных символов, а также в конце строки. Для этого PHP предоставляет функцию chunk_split () .

Таким образом, эти команды выводят одну и ту же строку:

chunk_split(base64_encode($json), 60, '\n'); // PHP
Base64.encode64(json) # Ruby

Но это не решает мою проблему

Результат по-прежнему отличается между PHP и Ruby:

PHP:

$json = '{"data":["bonjour"],"id":true,"price":false,"oper":null}';
$base64 = chunk_split(base64_encode($json), 60, '\n');
$hash = hash_hmac('sha1', $base64, 'bonjour');
// Ouput from var_dump()
eyJkYXRhIjpbImJvbmpvdXIiXSwiaWQiOnRydWUsInByaWNlIjpmYWxzZSwi\nb3BlciI6bnVsbH0=\n // $base64
fd044c309bea13396ed8df47b5c606d950222ceb // $hash

Сейчас в Ruby:

json_body = '{"data":["bonjour"],"id":true,"price":false,"oper":null}'
encoded_body = Base64.encode64(json_body)
hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 'bonjour', encoded_body)
# Ouput from puts var.inspect
eyJkYXRhIjpbImJvbmpvdXIiXSwiaWQiOnRydWUsInByaWNlIjpmYWxzZSwi\nb3BlciI6bnVsbH0=\n # base64
e168f9efe96e9424e22de765c72018c5a3f3437f # hash

Обратите внимание, что $base64 PHP и base64 Ruby переменные одинаковы.

Что я делаю не так? Я не знаю, Ruby, puts и .inspect - лучший способ отладки моего кода?

1 Ответ

1 голос
/ 17 января 2020

Кажется, Ruby добавляет новые строки в строку, закодированную в base64, а PHP - нет.

Ruby:

Base64.encode64('bonjour')
=> "Ym9uam91cg==\n"

PHP:

base64_encode('bonjour')
=> "Ym9uam91cg=="

Итак, теперь мы знаем, как исправить это в PHP:

hash_hmac('sha1', base64_encode('bonjour') . "\n", 'hello');
=> "62ac34e5d28563d6a50272d660805d1f8c791e41"

Или исправить это в Ruby:

OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 
                        'hello', Base64.encode64('bonjour').chomp)
=> "89ebf8bd3d92bf3283aa4c5f24072820258367e4"

Часть 2

В PHP, как и в Ruby, '\n' не совпадает с "\n". Первый выводит два символа (\, затем n), второй - перевод строки.

Таким образом, чтобы исправить ваш код, вам нужно использовать в строках символы новой строки, а не косой черты:

$base64 = chunk_split(base64_encode($json), 60, "\n");
                                                ^^^^

Вы также можете удалить строки из кодированной строки Ruby base64 с помощью gsub, что означает, что вам не нужно будет использовать какие-либо трюки в вашем PHP коде:

encoded_body = Base64.encode64(json_body).gsub("\n", '')
...