2015-10-30 4 views
3

Возможно, немного странный вопрос, но я пытаюсь реплицировать пример python, где они создают хэш HMAC SHA256 из серии параметров.Hex to string, путь python, в powershell

У меня возникла проблема, когда я должен переводить ключ api в hex в ascii и использовать его как секретный, но я просто не могу получить вывод таким же, как python.

>>> import hmac 
>>> import hashlib 
>>> apiKey = "76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b" 
>>> apiKey.decode('hex') 
'v\xb0,\x0cEC\xa8^EU$fiL\xf6w\x93x3\xc9\xcc\xe8\x7f\nb\x82H\xaf-,I[' 

Если я понял материал в Интернете, это должно представлять шестую строку в символах ascii.

Теперь скрипт Powershell:

$apikey = '76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b'; 

$hexstring = "" 

for($i=0; $i -lt $apikey.Length;$i=$i+2){ 
    $hexelement = [string]$apikey[$i] + [string]$apikey[$i+1] 
    $hexstring += [CHAR][BYTE][CONVERT]::toint16($hexelement,16) 
} 

Это выводит следующее:

v°,♀EC¨^EU$fiLöw?x3ÉÌè⌂ 
b?H¯-,I[ 

Они почти то же самое, но не совсем и использовать их в качестве секрета в HMAC создает различные результаты. Есть идеи?

Утверждение очевидного: Ключ в этом примере не является реальным ключом.

Обновление: Они выглядят более или менее одинаково, но кодировка вывода отличается. Я также проверил hex в ASCII в нескольких онлайн-функциях, и версия powershell кажется правильной.

У кого-нибудь есть идея, как сравнить два разных выхода?

Обновление 2: Я преобразовал каждый символ в целое, и оба Python и Powershell генерируют одинаковые числа, так как содержание должно быть одинаковым.

Прикрепление скрипты

Powershell:

Function generateToken { 

    Param($apikey, $url, $httpMethod, $queryparameters=$false, $postData=$false) 


    #$timestamp = [int]((Get-Date -UFormat %s).Replace(",", ".")) 
    $timestamp = "1446128942" 

    $datastring = $httpMethod + $url 

    if($queryparameters){ $datastring += $queryparameters } 
    $datastring += $timestamp 
    if($postData){ $datastring += $postData } 


    $hmacsha = New-Object System.Security.Cryptography.HMACSHA256 

    $apiAscii = HexToString -hexstring $apiKey 

    $hmacsha.key = [Text.Encoding]::ASCII.GetBytes($apiAscii) 
    $signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($datastring)) 
    $signature 
} 

Function HexToString { 

    Param($hexstring) 

    $asciistring = "" 

    for($i=0; $i -lt $hexstring.Length;$i=$i+2){ 
     $hexelement = [string]$hexstring[$i] + [string]$hexstring[$i+1] 
     $asciistring += [CHAR][BYTE][CONVERT]::toint16($hexelement,16) 
    } 

    $asciistring 
} 

Function TokenToHex { 

    Param([array]$Token) 

    $hexhash = "" 

    Foreach($element in $Token){ 
     $hexhash += '{0:x}' -f $element 
    } 

    $hexhash 
} 


$apiEndpoint = "http://test.control.llnw.com/traffic-reporting-api/v1" 
#what you see in Control on Edit My Profile page# 
$apikey = '76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b'; 
$queryParameters = "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01" 
$postData = "{param1: 123, param2: 456}" 

$token = generateToken -uri $apiEndpoint -httpMethod "GET" -queryparameters $queryParameters, postData=postData, -apiKey $apiKey 
TokenToHex -Token $token 

Python:

import hashlib 
import hmac 
import time 
try: import simplejson as json 
except ImportError: import json 
class HMACSample: 
     def generateSecurityToken(self, url, httpMethod, apiKey, queryParameters=None, postData=None): 
       #timestamp = str(int(round(time.time()*1000))) 
       timestamp = "1446128942" 
       datastring = httpMethod + url 
       if queryParameters != None : datastring += queryParameters 
       datastring += timestamp 
       if postData != None : datastring += postData 
       token = hmac.new(apiKey.decode('hex'), msg=datastring, digestmod=hashlib.sha256).hexdigest() 
       return token 
if __name__ == '__main__': 
     apiEndpoint = "http://test.control.llnw.com/traffic-reporting-api/v1" 
     #what you see in Control on Edit My Profile page# 
     apiKey = "76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b"; 
     queryParameters = "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01" 
     postData = "{param1: 123, param2: 456}" 
     tool = HMACSample() 
     hmac = tool.generateSecurityToken(url=apiEndpoint, httpMethod="GET", queryParameters=queryParameters, postData=postData, apiKey=apiKey) 
     print json.dumps(hmac, indent=4) 

apiKey с "тест" вместо преобразованный шестнадцатеричной в ASCII строка выводит то же значение, которое заставило меня подозревать что преобразование было проблемой. Теперь я не уверен, что верить.

/Patrik

+0

Какой вывод вы хотите получить от своих входных данных? – PetSerAl

ответ

3

символы поддержки кодировки ASCII из этого диапазона точки кода 0-127. Любой символ вне этого диапазона, закодированный байтом 63, который соответствует ?, в случае, если вы декодируете массив байтов обратно в строку. Таким образом, с вашим кодом вы разрушаете свой ключ, применяя к нему кодировку ASCII. Но если вы хотите массив байтов, то почему вы делаете Hex String -> ASCII String -> Byte Array вместо Hex String -> Byte Array?

Вот код PowerShell, которые генерируют те же результаты, как ваш код Python:

function GenerateToken { 
    param($apikey, $url, $httpMethod, $queryparameters, $postData) 

    $datastring = -join @(
     $httpMethod 
     $url 
     $queryparameters 
     #[DateTimeOffset]::Now.ToUnixTimeSeconds() 
     1446128942 
     $postData 
    ) 

    $hmacsha = New-Object System.Security.Cryptography.HMACSHA256 

    $hmacsha.Key = @($apikey -split '(?<=\G..)(?=.)'|ForEach-Object {[byte]::Parse($_,'HexNumber')}) 

    [BitConverter]::ToString($hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($datastring))).Replace('-','').ToLower() 
} 

$apiEndpoint = "http://test.control.llnw.com/traffic-reporting-api/v1" 
#what you see in Control on Edit My Profile page# 
$apikey = '76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b'; 
$queryParameters = "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01" 
$postData = "{param1: 123, param2: 456}" 

GenerateToken -url $apiEndpoint -httpMethod "GET" -queryparameters $queryParameters -postData $postData -apiKey $apiKey 

Я также исправить некоторые другие ошибки в коде PowerShell. В частности, аргументы для вызова функции GenerateToken. Кроме того, я изменяю ASCII на UTF8 для кодирования $datastring.UTF8 дает точно такие же байты, если все символы находятся в диапазоне ASCII, поэтому в вашем случае это не имеет значения. Но если вы хотите использовать символы из диапазона ASCII в $datastring, вы должны выбрать одну и ту же кодировку, как вы используете в Python, или вы не получите одинаковые результаты.

+0

Большое спасибо за ваш ответ! Я понял, что я видел только кодировку \ x__ при запуске кода в интерпретаторе. Однако мой сценарий powershell не дает одинаковых символов везде. Обновление дела. – PatrikJ

+0

@PatrikJ Я обновляю свой ответ. – PetSerAl

+0

Ты волшебник, который решил это! И я тоже кое-что узнал. Если вы когда-нибудь в Стокгольме, я должен вам немного пива. :) – PatrikJ