十六进制到字符串,python 方式,在 powershell 中

Hex to string, the python way, in powershell

这个问题可能有点奇怪,但我正在尝试复制一个 python 示例,他们从一系列参数创建 HMAC SHA256 散列。

我 运行 遇到了一个问题,我应该将十六进制的 api 密钥转换为 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['

如果我在网上理解 material 这应该是用 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 中将它们用作秘密会产生不同的结果。有什么想法吗?

Stating the obvious: The key in this example is no the real key.

更新: 它们看起来或多或少相同,但输出的编码不同。我还在多个在线函数中验证了 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 with "test" 而不是转换为 ASCII 字符串的十六进制输出相同的值,这让我怀疑转换是问题所在。现在我不知道该相信什么了。

/帕特里克

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 函数调用的参数。此外,我将 $datastring 编码的 ASCII 更改为 UTF8。如果所有字符都在 ASCII 范围内,UTF8 会产生完全相同的字节,因此在您的情况下无关紧要。但是如果你想在 $datastring 中使用超出 ASCII 范围的字符,那么你应该选择与在 Python 中使用的相同的编码,否则你将不会得到相同的结果。