哈希algorithm节点js与Python
我正试图将一个在Python上编写的哈希algorithm转换为node.js
Python代码看起来像
import uuid import hashlib import struct CLIENT_ID = uuid.UUID('c5f92e0d-e762-32cd-98cb-8c546c410dbe') SECRET = uuid.UUID('2cf26ff5-bd06-3245-becf-4d5a3baa704f') data = CLIENT_ID.bytes_le + SECRET.bytes_le + struct.pack("I", 2017) + struct.pack("I", 9) + struct.pack("I", 2) token = str(uuid.UUID(bytes_le=hashlib.sha256(data).digest()[0:16]))
生成的令牌是32d86f00-eb49-2739-e957-91513d2b9969
这里的date值struct.pack
值是使用datetime
时间生成的,但为了方便,我在这里硬编码。
我试图通过查看相应的库的python文档转换相同,做到目前为止
let CLIENT_ID = new Buffer('c5f92e0d-e762-32cd-98cb-8c546c410dbe'); let SECRET = new Buffer('2cf26ff5-bd06-3245-becf-4d5a3baa704f'); let d = new Buffer(2); let m = new Buffer(9); let y = new Buffer(2017); let data = CLIENT_ID+SECRET+y+m+d; const uuidv4 = require('uuid/v4'); const hash = crypto.createHash('sha256'); let token = uuidv4({random: hash.update(data, 'utf8').digest().slice(0, 16)}, 0);
而它产生的散列是b7b82474-eab4-4295-8318-cc258577ff9b
所以,基本上我很遗憾地忽略了nodejs部分。
你能指导我哪里出了问题。 谢谢您的帮助
实际上它有很多错过的部分。
节点部分:
-
new Buffer('c5')
不代表
<Buffer c5>
,但<Buffer 63 35>
。要编写c5,您需要使用
Buffer.from([0xc5])
或Buffer.from([197])
(dec)。 -
new Buffer(2)
不代表
<Buffer 02>
,它只分配2个字节。 -
CLIENT_ID+SECRET+y+m+d
缓冲区的连接不以这种方式工作。
使用数组缓冲区和
Buffer.concat([buffers])
来连接缓冲区。
uuid部分:
- 事实certificate,uuid操作缓冲区的修改版本(在Python代码中的
bytes_le
部分)
最有趣的部分:
-
在uuid的python版本中,如果没有版本参数被传递给
uuid.UUID(...)
,uuid会生成一个ID而不固定位根据RFC-4122 4.4 uuid 应该修复这些位 。
uuid.py跳过RFC-4122 4.4
node-uuid / v4.js修复了所需的位
即使sha256散列的结果相同,python和node之间的结果仍然会有所不同
python: 32d86f00-eb49-2739-e957-91513d2b9969 node: 32d86f00-eb49-4739-a957-91513d2b9969 ^ ^
所以,我在这里看到2个选项
- 将版本传递给python uuid(仅用于最后的uuid调用uuid.UUID(bytes_le = …,version = 4)),那样python会返回
32d86f00-eb49-4739-a957-91513d2b9969
- 如果没有办法在Python项目中更改源代码,我想有一个选项可以fork uuid并在
node-uuid/v4.js
删除两行代码?
请参阅下面的代码节点版本:
const uuidv4 = require('uuid/v4'); const crypto = require('crypto'); const hash = crypto.createHash('sha256'); const client_id_hex_str = "c5f92e0d-e762-32cd-98cb-8c546c410dbe".replace(/-/g, ""); const secret_hex_str = "2cf26ff5-bd06-3245-becf-4d5a3baa704f".replace(/-/g, ""); let CLIENT_ID = Buffer.from(to_bytes_le(to_bytes(client_id_hex_str, null, 16, 'big'))); let SECRET = Buffer.from(to_bytes_le(to_bytes(secret_hex_str, null, 16, 'big'))); let d = Buffer.from(to_bytes(null, 2, 4)); let m = Buffer.from(to_bytes(null, 9, 4)); let y = Buffer.from(to_bytes(null, 2017, 4)); let data = Buffer.concat([CLIENT_ID, SECRET, y, m, d]); let hashBytes = hash.update(data, 'utf8').digest().slice(0, 16); hashBytes = [].slice.call(hashBytes, 0); hashBytes = Buffer.from(to_bytes_le(hashBytes)); let token = uuidv4({random: hashBytes}); console.log(token); // https://stackoverflow.com/questions/16022556/has-python-3-to-bytes-been-back-ported-to-python-2-7 function to_bytes(hexString, number, length, endianess) { if (hexString == null && number == null) { throw new Error("Missing hex string or number."); } if (!length || isNaN(length)) { throw new Error("Missing or invalid bytes array length number."); } if (hexString && typeof hexString != "string") { throw new Error("Invalid format for hex value."); } if (hexString == null) { if (isNaN(number)) { throw new Error("Invalid number."); } hexString = number.toString(16); } let byteArray = []; if (hexString.length % 2 !== 0) { hexString = '0' + hexString; } const bitsLength = length * 2 hexString = ("0".repeat(bitsLength) + hexString).slice(-1 * bitsLength); for (let i = 0; i < hexString.length; i += 2) { const byte = hexString[i] + hexString[i + 1]; byteArray.push(parseInt(byte, 16)); } if (endianess !== "big") { byteArray = byteArray.reverse(); } return byteArray; } // https://github.com/python/cpython/blob/master/Lib/uuid.py#L258 function to_bytes_le(bytes) { const p1 = bytes.slice(0, 4).reverse(); const p2 = bytes.slice(4, 6).reverse(); const p3 = bytes.slice(6, 8).reverse(); const p4 = bytes.slice(8); const bytes_le = [].concat.apply([], [p1, p2, p3, p4]); return bytes_le; }
你想要数据的哈希与上面的Python代码相同吗? 如果没有,你可以看一下NodeJS下面的Sha256模块