为什么在 node.js 中尝试破解以太坊密钥库钱包文件时,我的所有输出都出现在每次暴力尝试之前

Why is all of my output appearing before each brute-force attempt when attempting to crack an ethereum keystore wallet file in node.js

我发现 a post 描述了如何通过猜测单个密码来恢复以太坊钱包密钥库,但是,它使用节点同步代码,我正在尝试将其转换为异步代码以便我可以使用使用 worker_threads.

的多线程

run.js(片段)

for (let x = 0; x <= maxX*passesPerThread; x++) {
  passes[x +1] = c.iterate(passes[x], chars)
}
for (let x = 0; x < maxX; x++) {
  dcWorker[x] = new Worker('./worker.js', { workerData: { FILE: FILE, PASSWORD: passes[x*passesPerThread], workerNum: x, passesPerThread: passesPerThread, CHARS: chars}, })
  dcWorker[x].on('message', (data) => {
    if (data.status === 'done') {
      console.log(" w" + x + "d")
    }
  })
}

crack.js(片段)

function crack(PASSWORD, FILE) {
  const data = fs.readFile(FILE, {encoding: "utf8"}, (err, data) => {
    if (err) throw err
    const content = data
    attempt(data, PASSWORD, FILE)
  })
}

function attempt(data, PASSWORD, FILE) {
  const keythereum = require("keythereum")
  const keyObject = JSON.parse(data)
  keythereum.recover(PASSWORD, keyObject, privateKey => {
    if (!privateKey.toString() === "message authentication code mismatch") {
      console.log("\npossible password: " + PASSWORD + "\naddress: " + `0x${keyObject.address}` + "\npriv key: " + `0x${privateKey}`)
      savePass(PASSWORD, FILE)
      //process.exit()
    }
  })
}

worker.js(片段)

passes = new Array()
passes[0] = pass
maxX = workerData.passesPerThread

const cProm = 
  new Promise((resolve, reject) => {
    for (let x = 1; x < maxX; x++) {
      passes[x] = c.iterate(passes[x -1], chars)
    }
    resolve('done')
  })
  .then(value => {
    for (let x = 1; x < maxX; x++) {
      process.stdout.write(" w" + workerData.workerNum + "a" + passes[x] + "T" + Date.now() + ", ")
      c.crack(passes[x], FILE)
    }
    parentPort.postMessage({ status: value })
  })
  .catch(err => {
    parentPort.postMessage({ status: err })
  })

我不明白为什么堆栈在实际尝试每次破解尝试之前处理所有输出。

以下是输出,然后在它尝试为每个线程破解一个密码时停顿很长时间,而不是像输出似乎表明的那样每个线程破解多个密码:

 w1aeasyaspsi, w1d
 w1aeasyaspsi,
 w1aeasyaspyeT1641634988273,  w1aeasyaspyaT1641634988274,  w1aeasyaspysT1641634988274,  w1aeasyaspyyT1641634988274,  w1aeasyaspypT1641634988274,  w1aeasyaspyiT1641634988274,  w1aeasyasppeT1641634988274,  w1aeasyasppaT1641634988274,  w1aeasyasppsT1641634988274,  w0aeasyaspaa, w3aeasyasiea, w0d
 w3d
 w0aeasyaspaa,
 w0aeasyaspasT1641634988279,  w0aeasyaspayT1641634988280,  w0aeasyaspapT1641634988280,  w0aeasyaspaiT1641634988280,  w0aeasyaspseT1641634988280,  w0aeasyaspsaT1641634988280,  w0aeasyaspssT1641634988280,  w0aeasyaspsyT1641634988280,  w0aeasyaspspT1641634988280,  w3aeasyasiea,
 w3aeasyasiesT1641634988279,  w3aeasyasieyT1641634988280,  w3aeasyasiepT1641634988280,  w3aeasyasieiT1641634988280,  w3aeasyasiaeT1641634988280,  w3aeasyasiaaT1641634988280,  w3aeasyasiasT1641634988280,  w3aeasyasiayT1641634988280,  w3aeasyasiapT1641634988280,  w2aeasyasppy, w2d
 w2aeasyasppy,
 w2aeasyaspppT1641634988296,  w2aeasyasppiT1641634988297,  w2aeasyaspieT1641634988297,  w2aeasyaspiaT1641634988297,  w2aeasyaspisT1641634988297,  w2aeasyaspiyT1641634988297,  w2aeasyaspipT1641634988297,  w2aeasyaspiiT1641634988298,  w2aeasyasieeT1641634988298,

在几乎瞬间输出后,它在尝试破解 4 个密码时暂停,然后进程退出(没有错误)。

我原以为输出会在每个逗号后暂停 , 但它会在尝试任何操作之前输出所有内容。

这个想法是,例如,每个线程破解 10 个密码,这里有 4 个线程,然后当 worker 终止时,一个新的 worker 会用接下来的 10 个密码启动,但是,我'我只是想 运行 每个 worker_thread 开始一次,直到我可以调试它的其余部分。

所以,我的问题是:

我放弃了理解 promises 的尝试(但我理解了一部分)所以我恢复了同步代码,同时仍然通过 nodejs cluster 实现真正的多线程,它现在运行得非常非常快比单线程

run.js

//(synchronous functions not displayed)
//...
workers = new Array()
if (cluster.isMaster) {
  pass = ""
  if(PROGRESS === "CONTINUE") {
    if (checkFileExists(FILE + ".progress.txt")) {
      console.log("progress file found: continuing")
      try {
        const data = fs.readFileSync(FILE + ".progress.txt", 'utf8')
        pass = data
      } catch (err) {
        console.error(err)
      }
      if (!pass.length > 0) pass = chars.substring(0,1)
    } else {
      console.log("progress file not found: starting at beginning; this is ok if first time running")
      pass = chars.substring(0,1)
    }
  } else pass = chars.substring(0,1)
  
  let r = 0
  let someLeft = true
  let passes = new Array()
  passes[0] = pass
  for (let y = 1; y < cpuCount; y++) passes[y] = iterate(passes[y -1])
  let passTried = new Array()
  for (let y = 0; y < cpuCount; y++) passTried[y] = false
  for (let x = 0; x < cpuCount; x++) {
    workers[x] = cluster.fork()
    passTried[x] = true
    workers[x].send({ message: passes[x] })
    workers[x].on('message', function(msg) {
      if (msg.stat) {
        for (sworker in workers) {
          workers[sworker].process.kill()
        }
        process.exit()
      }
      if (msg.att) {
        process.stdout.write("\rattempted: " + msg.att)
        r++
        if (r % 100 == 0) {
          fs.writeFileSync(FILE + '.progress.txt', msg.att, function (err) {
            if (err) throw err
          })
          r = 0
        }
        for (let i = 0; i < cpuCount; i++) {
          if (!passTried[i]) {
        passTried[i] = true
            workers[x].send({ message: passes[i] })
            break
      }
    }
        someLeft = false
        for (let i = 0; i < cpuCount; i++) {
          if (!passTried[i]) {
        someLeft = true
            break
      }
    }
        if (!someLeft) {
      passes = getNewBlock(passes)
          for (let y = 0; y < cpuCount; y++) passTried[y] = false
          someLeft = true
    }
      }
    })
  }
} else {
  process.on('message', function(pass) {
    crack(pass.message)
    process.send({ att: pass.message })
  })
}

请注意,这是一个有点丑陋的 hack-job,不应该在服务器中实现,绝对不应该在生产中实现,因为它使用阻塞代码,但出于我狭隘的目的,它完成了工作

感谢在上面的评论中试图向我展示使用异步代码的方法的所有人