4

我发现一篇文章描述了如何通过猜测单个密码来恢复以太坊钱包密钥库,但是,它使用节点同步代码,我正在尝试将其转换为异步代码,以便我可以使用 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")
    }
  })
}

破解.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 个线程,然后当工作人员终止时,将使用接下来的 10 个密码启动一个新工作人员,但是,我只是想运行每个 worker_thread 启动一次,直到我可以调试它的其余部分。

所以,我的问题是:

  • 为什么它不尝试输出似乎表明的所有破解尝试?
  • 如何使输出与尝试时实际尝试的内容保持一致?
4

1 回答 1

0

我放弃了试图理解承诺(但我理解了其中的一部分),所以我恢复到同步代码,同时仍然通过实现真正的多线程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 })
  })
}

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

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

于 2022-01-13T08:34:24.113 回答