проверка подлинности — проверка HMAC с помощью специального бота Microsoft Teams в переполнении стека

Я пытаюсь проверить подлинность собственного бота Microsoft Teams с помощью PHP, следуя указаниям Microsoft. инструкции и прочитайте пример кода C #.

Microsoft Intructions шаги:
1. Сгенерируйте hmac из тела запроса сообщения. На большинстве платформ есть стандартные библиотеки. Microsoft Teams использует стандарт
SHA256 HMAC криптография. Вам нужно будет преобразовать тело в байт
массив в UTF8.
2. Чтобы вычислить хеш, предоставьте байтовый массив общего секрета.
3. Преобразуйте хеш в строку, используя кодировку UTF8.
4. Сравните строковое значение сгенерированного хэша со значением, указанным в HTTP-запросе.

Я должен был написать небольшой скрипт php, чтобы проверить это на локальном компьютере:

        <?php
//Function to generate C# byte[] equivalent
function unpak_str($val){
$b = unpack('C*', $val);
foreach ($b as $key => $value)
$byte_a .= $value;

return $byte_a;
}

//multi test outputs
function hasher($values=[], &$output){
//my secret share
$secret="ejWiKHgsKY1ZfpJwJ+wIiN4+bgsFad/lkpu9/MWNXgM=";
//diferent test
$secret_64=base64_decode($secret);
$secret_b=unpak_str($secret);
$secret_b_64=unpak_str(base64_decode($secret));

foreach($values as $msg){
$hs = hash_hmac("sha256",$msg,$secret, true);
$hs_64 = hash_hmac("sha256",$msg,$secret_64, true);
$hs_b = hash_hmac("sha256",$msg,$secret_b, true);
$hs_b_64 = hash_hmac("sha256",$msg,$secret_b_64, true);

$output.=base64_encode($hs)." <BR>";
$output.=base64_encode($hs_64)." <BR>";
$output.=base64_encode($hs_b)." <BR>";
$output.=base64_encode($hs_b_64)." <BR>";
}
}

//Get data
$data=file_get_contents('php://input');

//real data request content for test
$data ='{type":"message","id":"1512376018086","timestamp":"2017-12-04T08:26:58.237Z","localTimestamp":"2017-12-04T09:26:58.237+01:00","serviceUrl":"https://smba.trafficmanager.net/emea-client-ss.msg/","channelId":"msteams","from":{"id":"29:1aq6GCrC6lM9dv3YkAYi1gxTPiLnojGFgVr0_Th-2x6DhqmHAOhFwQHFzSyDy5RruXY4_FZjJebKHU7bpxfHpXA","name":"ROBERTO ALONSO FERNANDEZ","aadObjectId":"1e0dc7a0-9d5e-488b-bcf2-7e39c84076b8"},"conversation":{"isGroup":true,"id":"19:[email protected];messageid=1512376018086","name":null},"recipient":null,"textFormat":"plain","attachmentLayout":null,"membersAdded":[],"membersRemoved":[],"topicName":null,"historyDisclosed":null,"locale":null,"text":"<at>PandoBot</at> fff","speak":null,"inputHint":null,"summary":null,"suggestedActions":null,"attachments":[{"contentType":"text/html","contentUrl":null,"content":"<div><span itemscope=\"\" itemtype=\"http://schema.skype.com/Mention\" itemid=\"0\">PandoBot</span> fff</div>","name":null,"thumbnailUrl":null}],"entities":[{"type":"clientInfo","locale":"es-ES","country":"ES","platform":"iOS"}],"channelData":{"teamsChannelId":"19:[email protected]","teamsTeamId":"19:[email protected]","channel":{"id":"19:[email protected]"},"team":{"id":"19:[email protected]"},"tenant":{"id":"9744600e-3e04-492e-baa1-25ec245c6f10"}},"action":null,"replyToId":null,"value":null,"name":null,"relatesTo":null,"code":null}';//generate HMAC hash with diferent $data formats
$test = [$data, unpak_str($data), base64_encode($data), unpak_str(base64_encode($data))];
hasher($test, $output);//microsoft provided HMAC
$output.="<HR>EW2993goL1q7nGhytIb3jKmV6luXLz15Bq2aYwuCeiE=";echo $output;
/*
Calculates:
0HsKoHza/QBvdz+nZw9tOti/eSWjyMMt/U77bfDqiE8=
3jSq3I0HNQkjB9QfnnsxC1c3pF5PjqweHlSVcicrShY=
bTQcGVTHX8/Gh4xovnN0WiJUiNaOQwvUZnwyFfiCaJE=
qHBT2Y2ITyoxz2gmBbG8P1CrClvETus6dTffET3bAR8=
8BcrXEQDDi77qgxCZLYyb/6ez8p9Qg2ZhTyZPWkdn/g=
+8RSU5SSJKxqRLKkI+NkTE01xwu6PwPkKKMuvyyUvlo=
PdL5ZpEwcN6Fe5kfX7zeAZLJvt0uLNTzu7lhuoOcr2o=
s6M5pYruEgWeNMEOFfQRjVKQqtPBVaW3TJb2MzObF2c=
xOTLhddbAwczQVneuTDQhPzmoIXGQljpf27c+hlhQII=
aUMm5b2sKfmwGZOglfiu228fWqoLlwjc7z1QRdIbakE=
5a7bAj9tzqhP9l85OvfVasURW0GSV5rykRutFFPO2fk=
kwg6P2LoDL9rc3SSwJxQeoYJzZYlh+FHFefe38UokBM=
eHeAzI7TV6vYDzxTxwyKWxMeVKFiFlIffWRiIMAk6fk=
ZCyj2UppacQOTXogLPMFLDeMArQg03rhhlIwhynDvng=
uQYK+7u9fppb62zXqtVYfkNK9wVawB3g+BlTyu4dc74=
vjOFA3fqpwUx/VO9dQv3XviNhpjTNQsUwaJIwH4JjdY=
------------ MS PROVIDED HMAC ---------------
EW2993goL1q7nGhytIb3jKmV6luXLz15Bq2aYwuCeiE=
*/

У меня нулевое совпадение хешей …

0

Решение

Я не эксперт по PHP, и ваша логика для охвата всех случаев немного запутана, но я уверен, что ваша проблема в том, что вы не конвертируете сообщение ($ data) из UTF8 до вычисления HMAC.

Вот простой настраиваемый эхо-бот в Node, который показывает, как вычислить и проверить HMAC:

const util = require('util');
const crypto = require('crypto');
const sharedSecret = "+ZaRRMC8+mpnfGaGsBOmkIFt98bttL5YQRq3p2tXgcE=";
const bufSecret = Buffer(sharedSecret, "base64");

var http = require('http');
var PORT = process.env.port || process.env.PORT || 8080;

http.createServer(function(request, response) {
var payload = '';
request.on('data', function (data) {
// console.log("Chunk size: %s bytes", data.length)
payload += data;
});

request.on('end', function() {
try {
// Retrieve authorization HMAC information
var auth = this.headers['authorization'];
// Calculate HMAC on the message we've received using the shared secret
var msgBuf = Buffer.from(payload, 'utf8');
var msgHash = "HMAC " + crypto.createHmac('sha256', bufSecret).update(msgBuf).digest("base64");
console.log("Computed HMAC: " + msgHash);
console.log("Received HMAC: " + auth);

response.writeHead(200);
if (msgHash === auth) {
var receivedMsg = JSON.parse(payload);
var responseMsg = '{ "type": "message", "text": "You typed: ' + receivedMsg.text + '" }';
} else {
var responseMsg = '{ "type": "message", "text": "Error: message sender cannot be authenticated." }';
}
response.write(responseMsg);
response.end();
}
catch (err) {
response.writeHead(400);
return response.end("Error: " + err + "\n" + err.stack);
}
});

}).listen(PORT);

console.log('Listening on port %s', PORT);
1

Другие решения

Наконец, после долгих испытаний, я сошел с ума и решил запустить нового бота с новым секретом. Сейчас работает нормально. Я — человек, в то время как MS Teams нет … Я полагаю, что это была моя ошибка с копированием / вставкой, но это действительно странная вещь, и старый бот часто терпит неудачу без ответа, а новейший нет.

Полный пример проверки HMAC в PHP для Microsoft Teams Custom Bot:

        <?php

//The secret share with Microsoft Teams
$secret="jond3021g9imMkrt8txF5AVPIwPFouNV/I72cQFii18=";

//get headers
$a = getallheaders();
$provided_hmac=substr($a['Authorization'],5);

//Get data from request
$data=file_get_contents('php://input');

//json decode into array
$json=json_decode($data, true);

//hashing
$hash = hash_hmac("sha256",$data,base64_decode($secret), true);
$calculated_hmac = base64_encode($hash);

//start log var
$log = "\n========".date("Y-m-d H:i:s")."========\n".$provided_hmac."\n".$calculated_hmac."\n";

try{
//compare hashs
if(!hash_equals($provided_hmac,$calculated_hmac))
throw new Exception("No hash matching");
//response text
$txt="Hi {$json["from"]["name"]} welcome to your custom bot";
echo '{
"type": "message",
"text": "'.$txt.'"}';
$log .= "Sended: {$txt}";
}catch (Exception $e){
$log .= $e->getMessage();
}
//write log
$fp = fopen("log.txt","a");
fwrite($fp, $log . PHP_EOL);
fclose($fp);
1

Вам не нужно unpack(), или это unpak_str() функция (которая также не работает, потому что она просто перезаписывает каждый байт следующим, не добавляя их).

Массивы байтов не являются чем-то особенным в PHP — язык не имеет разных типов строк; как интерпретируются строки, полностью зависит от функций, использующих их. То есть ваш общий секрет должен быть только результатом base64_encode($secret),

0
По вопросам рекламы [email protected]