十六进制到字符串,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 中使用的相同的编码,否则你将不会得到相同的结果。
这个问题可能有点奇怪,但我正在尝试复制一个 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 中使用的相同的编码,否则你将不会得到相同的结果。