【问题标题】:How do I make the same SHA256 encoded string in Javascript that I do in Python 3?如何在 Javascript 中创建与在 Python 3 中相同的 SHA256 编码字符串?
【发布时间】:2020-04-14 15:14:13
【问题描述】:

我有这个 Python 脚本可以产生正确的输出:

import hashlib

username = "LoginUser"
password = "LoginPass"
nonce = "1234567890"

def LowerCase(s): return s.lower()
def Hex(s): return ''.join([hex(char)[2:] for char in s])

def SHA1(s): h = hashlib.sha1(); h.update(s); return h.digest()
def SHA1Raw(s): h = hashlib.sha1(); h.update(s); return h.hexdigest()

def SHA256(s): h = hashlib.sha256(); h.update(s); return h.digest()
def SHA256Raw(s): h = hashlib.sha256(); h.update(s); return h.hexdigest()

def UTF8Encode(s): return str.encode(s)



step1 = SHA256((UTF8Encode(username)))
step2 = SHA1((UTF8Encode(password)))

step3 = SHA256Raw(step1 + step2)

step1 = SHA256Raw((UTF8Encode(username)))
step2 = SHA1Raw((UTF8Encode(password)))


print("""
SHA256(username={username})                            =    {step1}
SHA1(password={password})                              =    {step2}
SHA256((username + password)={username}{password})     =    {step3}
""".format(
    username = username,
    password = password,
    step1 = step1,
    step2 = step2,
    step3 = step3
))

输出:

PS D:\project> python .\test.py
SHA256(username=LoginUser)                            =    7981673b2c73a6bdb665f347dc89e9d324f542b1fa1c4a700bc523d8a9a6f565  
SHA1(password=LoginPass)                              =    df703733447469593d39a125ca93462eade53cab
SHA256((username + password)=LoginUserLoginPass)     =    cf3066e157468d6a9d59f9ff0662e4f8f8432be4e07c68320a8b6a031d0c022b

现在在 Javascript 中,我尝试镜像 Python 中的函数。我不能为我的生活。我尝试在这种情况下快速理解缓冲区和流,但我相信我只是因为没有扎根于某事而进一步混淆了自己。

无论如何,这里是 Javascript 版本a 和它的输出:

const crypto = require('crypto')

const username = "LoginUser"
const password = "LoginPass"
const nonce = "1234567890"

const LowerCase = s => s.toLowerCase()
const Hex = s => Buffer.from(s, 'utf8').toString('hex')

const SHA1 = s => crypto.createHash('sha1').update(s, 'utf8').digest('hex')
const SHA1Raw = s => crypto.createHash('sha1').update(s, 'utf8').digest()

const SHA256 = s => crypto.createHash('sha256').update(s, 'utf8').digest('hex')
const SHA256Raw = s => crypto.createHash('sha256').update(s, 'utf8').digest()

const UTF8Encode = s => Buffer.from(s, 'utf8');


let step1 = SHA256(username)
let step2 = SHA1(password)
let step3 = SHA256Raw(step1.concat(step2))

console.log(`
SHA256(username=${username})                            =    ${step1}
SHA1(password=${password})                              =    ${step2}
SHA256((username + password)=${username+password})      =    ${step3.toString('hex')}
`)

输出:

PS D:\project> node .\test.js


SHA256(username=LoginUser)                            =    7981673b2c73a6bdb665f347dc89e9d324f542b1fa1c4a700bc523d8a9a6f565
SHA1(password=LoginPass)                              =    df703733447469593d39a125ca93462eade53cab
SHA256((username + password)=LoginUserLoginPass)      =    757101f0fd2628ce12dc039146f56da14a1e85a27fda5d68c2623f616c4fc3cc

谁能帮忙?

【问题讨论】:

  • 无论你在做什么,都不要这样保存密码。使用正确的密码散列函数,如 Argon2。
  • 这是 5 个阶段的前 3 个阶段,用于散列第 3 方 API AuthenticationRequest 的密码
  • 您似乎将原始和十六进制编码的哈希值弄得一团糟。 757101f0fd2628ce12dc039146f56da14a1e85a27fda5d68c2623f616c4fc3cc 是十六进制字符串 7981673b2c73a6bdb665f347dc89e9d324f542b1fa1c4a700bc523d8a9a6f565 + df703733447469593d39a125ca93462eade53cab 的 sha256 哈希。您的 Python 代码正在计算相应字节数组 [0x79, 0x81, 0x67, 0x2c, 0x73, 0xa6, ...etc...]
  • @r3mainer 如何在 javascript 中计算字节数组的哈希值?我尝试创建一个缓冲区并循环通过它来更新哈希,但这给了我相同的输出。
  • 在计算哈希之前为什么不直接convert the hex data to a string of bytes

标签: javascript python node.js python-3.x cryptography


【解决方案1】:

您只需要进行非常小的修改即可在 Node.js 中进行这项工作。

我建议将哈希计算为缓冲区对象,这使得组合哈希更容易计算(因为我们不需要从十六进制解析)。

我们通过使用Buffer.concat 连接先前哈希的输出来做到这一点。

const crypto = require('crypto')

const username = "LoginUser"
const password = "LoginPass"
const nonce = "1234567890"

const LowerCase = s => s.toLowerCase()
const Hex = s => Buffer.from(s, 'utf8').toString('hex')

const SHA1 = s => crypto.createHash('sha1').update(s, 'utf8').digest('hex')
const SHA1Raw = s => crypto.createHash('sha1').update(s, 'utf8').digest()

const SHA256 = s => crypto.createHash('sha256').update(s, 'utf8').digest('hex')
const SHA256Raw = s => crypto.createHash('sha256').update(s, 'utf8').digest()

const UTF8Encode = s => Buffer.from(s, 'utf8');


let step1 = SHA256Raw(username) // Get the SHA256 as a buffer.
let step2 = SHA1Raw(password) // Get the SHA1 as a buffer.
let step3 = SHA256Raw(Buffer.concat([step1, step2])) // Get the SHA256 of the previous steps concatenated as a buffer.

console.log(`
SHA256(username=${username})                            =    ${step1.toString('hex')}
SHA1(password=${password})                              =    ${step2.toString('hex')}
SHA256((username + password)=${username+password})      =    ${step3.toString('hex')}
`)

这给出了正确的结果,例如

SHA256(username=LoginUser)                            =    7981673b2c73a6bdb665f347dc89e9d324f542b1fa1c4a700bc523d8a9a6f565
SHA1(password=LoginPass)                              =    df703733447469593d39a125ca93462eade53cab
SHA256((username + password)=LoginUserLoginPass)      =    cf3066e157468d6a9d59f9ff0662e4f8f8432be4e07c68320a8b6a031d0c022b

【讨论】:

  • 谢谢!完美运行。我尝试了上述将 step1+2 字符串转换为字节数组的方法,但我得到了格式错误的结果。我想我没有预见到 Buffer.concat() 方法是这里的解决方案。再次,我要致以最崇高的谢意。我将阅读 Javascript 中的 Buffer 类型,并尝试更清楚地了解这里发生的情况。从十六进制解析似乎是一个多余/不必要的步骤,所以我必须加深对它的理解。
  • 很高兴听到它,Python 似乎可以更无缝地处理连接。 Buffer.concat 是真正的 Node 事物。无论如何,这是一个很小的变化,但是是的,试图找到最后一行代码可能会令人沮丧!
猜你喜欢
  • 2021-11-27
  • 2023-03-09
  • 2016-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 2017-11-25
相关资源
最近更新 更多