seaking001 (OP)
Newbie
Offline
Activity: 42
Merit: 0
|
|
January 13, 2018, 03:05:33 AM |
|
For help. I lose the Bip38 passphrase of my DeepOnion Wallet paper wallet, Please check the post for details,https://bitcointalk.org/index.php?topic=2735431.0 I found this javascript on Github, https://github.com/bitcoinjs/bip38/blob/master/index.js ,I am learning how to use it. Can anyone help me and other people who lost their password? var aes = require('browserify-aes') var assert = require('assert') var Buffer = require('safe-buffer').Buffer var bs58check = require('bs58check') var createHash = require('create-hash') var scrypt = require('scryptsy') var xor = require('buffer-xor/inplace')
var ecurve = require('ecurve') var curve = ecurve.getCurveByName('secp256k1')
var BigInteger = require('bigi')
// constants var SCRYPT_PARAMS = { N: 16384, // specified by BIP38 r: 8, p: 8 } var NULL = Buffer.alloc(0)
function hash160 (buffer) { return createHash('rmd160').update( createHash('sha256').update(buffer).digest() ).digest() }
function hash256 (buffer) { return createHash('sha256').update( createHash('sha256').update(buffer).digest() ).digest() }
function getAddress (d, compressed) { var Q = curve.G.multiply(d).getEncoded(compressed) var hash = hash160(Q) var payload = Buffer.allocUnsafe(21) payload.writeUInt8(0x00, 0) // XXX TODO FIXME bitcoin only??? damn you BIP38 hash.copy(payload, 1)
return bs58check.encode(payload) }
function encryptRaw (buffer, compressed, passphrase, progressCallback, scryptParams) { if (buffer.length !== 32) throw new Error('Invalid private key length') scryptParams = scryptParams || SCRYPT_PARAMS
var d = BigInteger.fromBuffer(buffer) var address = getAddress(d, compressed) var secret = Buffer.from(passphrase, 'utf8') var salt = hash256(address).slice(0, 4)
var N = scryptParams.N var r = scryptParams.r var p = scryptParams.p
var scryptBuf = scrypt(secret, salt, N, r, p, 64, progressCallback) var derivedHalf1 = scryptBuf.slice(0, 32) var derivedHalf2 = scryptBuf.slice(32, 64)
var xorBuf = xor(derivedHalf1, buffer) var cipher = aes.createCipheriv('aes-256-ecb', derivedHalf2, NULL) cipher.setAutoPadding(false) cipher.end(xorBuf)
var cipherText = cipher.read()
// 0x01 | 0x42 | flagByte | salt (4) | cipherText (32) var result = Buffer.allocUnsafe(7 + 32) result.writeUInt8(0x01, 0) result.writeUInt8(0x42, 1) result.writeUInt8(compressed ? 0xe0 : 0xc0, 2) salt.copy(result, 3) cipherText.copy(result, 7)
return result }
function encrypt (buffer, compressed, passphrase, progressCallback, scryptParams) { return bs58check.encode(encryptRaw(buffer, compressed, passphrase, progressCallback, scryptParams)) }
// some of the techniques borrowed from: https://github.com/pointbiz/bitaddress.org function decryptRaw (buffer, passphrase, progressCallback, scryptParams) { // 39 bytes: 2 bytes prefix, 37 bytes payload if (buffer.length !== 39) throw new Error('Invalid BIP38 data length') if (buffer.readUInt8(0) !== 0x01) throw new Error('Invalid BIP38 prefix') scryptParams = scryptParams || SCRYPT_PARAMS
// check if BIP38 EC multiply var type = buffer.readUInt8(1) if (type === 0x43) return decryptECMult(buffer, passphrase, progressCallback, scryptParams) if (type !== 0x42) throw new Error('Invalid BIP38 type')
passphrase = Buffer.from(passphrase, 'utf8')
var flagByte = buffer.readUInt8(2) var compressed = flagByte === 0xe0 if (!compressed && flagByte !== 0xc0) throw new Error('Invalid BIP38 compression flag')
var N = scryptParams.N var r = scryptParams.r var p = scryptParams.p
var salt = buffer.slice(3, 7) var scryptBuf = scrypt(passphrase, salt, N, r, p, 64, progressCallback) var derivedHalf1 = scryptBuf.slice(0, 32) var derivedHalf2 = scryptBuf.slice(32, 64)
var privKeyBuf = buffer.slice(7, 7 + 32) var decipher = aes.createDecipheriv('aes-256-ecb', derivedHalf2, NULL) decipher.setAutoPadding(false) decipher.end(privKeyBuf)
var plainText = decipher.read() var privateKey = xor(derivedHalf1, plainText)
// verify salt matches address var d = BigInteger.fromBuffer(privateKey) var address = getAddress(d, compressed) var checksum = hash256(address).slice(0, 4) assert.deepEqual(salt, checksum)
return { privateKey: privateKey, compressed: compressed } }
function decrypt (string, passphrase, progressCallback, scryptParams) { return decryptRaw(bs58check.decode(string), passphrase, progressCallback, scryptParams) }
function decryptECMult (buffer, passphrase, progressCallback, scryptParams) { passphrase = Buffer.from(passphrase, 'utf8') buffer = buffer.slice(1) // FIXME: we can avoid this scryptParams = scryptParams || SCRYPT_PARAMS
var flag = buffer.readUInt8(1) var compressed = (flag & 0x20) !== 0 var hasLotSeq = (flag & 0x04) !== 0
assert.equal((flag & 0x24), flag, 'Invalid private key.')
var addressHash = buffer.slice(2, 6) var ownerEntropy = buffer.slice(6, 14) var ownerSalt
// 4 bytes ownerSalt if 4 bytes lot/sequence if (hasLotSeq) { ownerSalt = ownerEntropy.slice(0, 4)
// else, 8 bytes ownerSalt } else { ownerSalt = ownerEntropy }
var encryptedPart1 = buffer.slice(14, 22) // First 8 bytes var encryptedPart2 = buffer.slice(22, 38) // 16 bytes
var N = scryptParams.N var r = scryptParams.r var p = scryptParams.p var preFactor = scrypt(passphrase, ownerSalt, N, r, p, 32, progressCallback)
var passFactor if (hasLotSeq) { var hashTarget = Buffer.concat([preFactor, ownerEntropy]) passFactor = hash256(hashTarget) } else { passFactor = preFactor }
var passInt = BigInteger.fromBuffer(passFactor) var passPoint = curve.G.multiply(passInt).getEncoded(true)
var seedBPass = scrypt(passPoint, Buffer.concat([addressHash, ownerEntropy]), 1024, 1, 1, 64) var derivedHalf1 = seedBPass.slice(0, 32) var derivedHalf2 = seedBPass.slice(32, 64)
var decipher = aes.createDecipheriv('aes-256-ecb', derivedHalf2, Buffer.alloc(0)) decipher.setAutoPadding(false) decipher.end(encryptedPart2)
var decryptedPart2 = decipher.read() var tmp = xor(decryptedPart2, derivedHalf1.slice(16, 32)) var seedBPart2 = tmp.slice(8, 16)
var decipher2 = aes.createDecipheriv('aes-256-ecb', derivedHalf2, Buffer.alloc(0)) decipher2.setAutoPadding(false) decipher2.write(encryptedPart1) // first 8 bytes decipher2.end(tmp.slice(0, 8)) // last 8 bytes
var seedBPart1 = xor(decipher2.read(), derivedHalf1.slice(0, 16)) var seedB = Buffer.concat([seedBPart1, seedBPart2], 24) var factorB = BigInteger.fromBuffer(hash256(seedB))
// d = passFactor * factorB (mod n) var d = passInt.multiply(factorB).mod(curve.n)
return { privateKey: d.toBuffer(32), compressed: compressed } }
function verify (string) { var decoded = bs58check.decodeUnsafe(string) if (!decoded) return false
if (decoded.length !== 39) return false if (decoded.readUInt8(0) !== 0x01) return false
var type = decoded.readUInt8(1) var flag = decoded.readUInt8(2)
// encrypted WIF if (type === 0x42) { if (flag !== 0xc0 && flag !== 0xe0) return false
// EC mult } else if (type === 0x43) { if ((flag & ~0x24)) return false } else { return false }
return true }
module.exports = { decrypt: decrypt, decryptECMult: decryptECMult, decryptRaw: decryptRaw, encrypt: encrypt, encryptRaw: encryptRaw, verify: verify }
|