PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/bitcoinjs-message
Просмотр файла: index.js
const bs58check = require('bs58check')
const bech32 = require('bech32')
const bufferEquals = require('buffer-equals')
const createHash = require('create-hash')
const secp256k1 = require('secp256k1')
const varuint = require('varuint-bitcoin')
const SEGWIT_TYPES = {
P2WPKH: 'p2wpkh',
P2SH_P2WPKH: 'p2sh(p2wpkh)'
}
function sha256 (b) {
return createHash('sha256')
.update(b)
.digest()
}
function hash256 (buffer) {
return sha256(sha256(buffer))
}
function hash160 (buffer) {
return createHash('ripemd160')
.update(sha256(buffer))
.digest()
}
function encodeSignature (signature, recovery, compressed, segwitType) {
if (segwitType !== undefined) {
recovery += 8
if (segwitType === SEGWIT_TYPES.P2WPKH) recovery += 4
} else {
if (compressed) recovery += 4
}
return Buffer.concat([Buffer.alloc(1, recovery + 27), signature])
}
function decodeSignature (buffer) {
if (buffer.length !== 65) throw new Error('Invalid signature length')
const flagByte = buffer.readUInt8(0) - 27
if (flagByte > 15 || flagByte < 0) {
throw new Error('Invalid signature parameter')
}
return {
compressed: !!(flagByte & 12),
segwitType: !(flagByte & 8)
? null
: !(flagByte & 4)
? SEGWIT_TYPES.P2SH_P2WPKH
: SEGWIT_TYPES.P2WPKH,
recovery: flagByte & 3,
signature: buffer.slice(1)
}
}
function magicHash (message, messagePrefix) {
messagePrefix = messagePrefix || '\u0018Bitcoin Signed Message:\n'
if (!Buffer.isBuffer(messagePrefix)) {
messagePrefix = Buffer.from(messagePrefix, 'utf8')
}
if (!Buffer.isBuffer(message)) {
message = Buffer.from(message, 'utf8')
}
const messageVISize = varuint.encodingLength(message.length)
const buffer = Buffer.allocUnsafe(
messagePrefix.length + messageVISize + message.length
)
messagePrefix.copy(buffer, 0)
varuint.encode(message.length, buffer, messagePrefix.length)
message.copy(buffer, messagePrefix.length + messageVISize)
return hash256(buffer)
}
function prepareSign (
messagePrefixArg,
sigOptions
) {
if (typeof messagePrefixArg === 'object' && sigOptions === undefined) {
sigOptions = messagePrefixArg
messagePrefixArg = undefined
}
let { segwitType, extraEntropy } = sigOptions || {}
if (
segwitType &&
(typeof segwitType === 'string' || segwitType instanceof String)
) {
segwitType = segwitType.toLowerCase()
}
if (
segwitType &&
segwitType !== SEGWIT_TYPES.P2SH_P2WPKH &&
segwitType !== SEGWIT_TYPES.P2WPKH
) {
throw new Error(
'Unrecognized segwitType: use "' +
SEGWIT_TYPES.P2SH_P2WPKH +
'" or "' +
SEGWIT_TYPES.P2WPKH +
'"'
)
}
return {
messagePrefixArg,
segwitType,
extraEntropy
}
}
function isSigner (obj) {
return obj && typeof obj.sign === 'function'
}
function sign (
message,
privateKey,
compressed,
messagePrefix,
sigOptions
) {
const {
messagePrefixArg,
segwitType,
extraEntropy
} = prepareSign(messagePrefix, sigOptions)
const hash = magicHash(message, messagePrefixArg)
const sigObj = isSigner(privateKey)
? privateKey.sign(hash, extraEntropy)
: secp256k1.ecdsaSign(hash, privateKey, { data: extraEntropy })
return encodeSignature(
sigObj.signature,
sigObj.recid,
compressed,
segwitType
)
}
function signAsync (
message,
privateKey,
compressed,
messagePrefix,
sigOptions
) {
let messagePrefixArg, segwitType, extraEntropy
return Promise.resolve().then(() => {
({
messagePrefixArg,
segwitType,
extraEntropy
} = prepareSign(messagePrefix, sigOptions))
const hash = magicHash(message, messagePrefixArg)
return isSigner(privateKey)
? privateKey.sign(hash, extraEntropy)
: secp256k1.ecdsaSign(hash, privateKey, { data: extraEntropy })
}).then((sigObj) => {
return encodeSignature(
sigObj.signature,
sigObj.recid,
compressed,
segwitType
)
})
}
function segwitRedeemHash (publicKeyHash) {
const redeemScript = Buffer.concat([
Buffer.from('0014', 'hex'),
publicKeyHash
])
return hash160(redeemScript)
}
function decodeBech32 (address) {
const result = bech32.decode(address)
const data = bech32.fromWords(result.words.slice(1))
return Buffer.from(data)
}
function verify (message, address, signature, messagePrefix, checkSegwitAlways) {
if (!Buffer.isBuffer(signature)) signature = Buffer.from(signature, 'base64')
const parsed = decodeSignature(signature)
if (checkSegwitAlways && !parsed.compressed) {
throw new Error('checkSegwitAlways can only be used with a compressed pubkey signature flagbyte')
}
const hash = magicHash(message, messagePrefix)
const publicKey = secp256k1.ecdsaRecover(
parsed.signature,
parsed.recovery,
hash,
parsed.compressed
)
const publicKeyHash = hash160(publicKey)
let actual, expected
if (parsed.segwitType) {
if (parsed.segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
actual = segwitRedeemHash(publicKeyHash)
expected = bs58check.decode(address).slice(1)
} else {
// parsed.segwitType === SEGWIT_TYPES.P2WPKH
// must be true since we only return null, P2SH_P2WPKH, or P2WPKH
// from the decodeSignature function.
actual = publicKeyHash
expected = decodeBech32(address)
}
} else {
if (checkSegwitAlways) {
try {
expected = decodeBech32(address)
// if address is bech32 it is not p2sh
return bufferEquals(publicKeyHash, expected)
} catch (e) {
const redeemHash = segwitRedeemHash(publicKeyHash)
expected = bs58check.decode(address).slice(1)
// base58 can be p2pkh or p2sh-p2wpkh
return (
bufferEquals(publicKeyHash, expected) ||
bufferEquals(redeemHash, expected)
)
}
} else {
actual = publicKeyHash
expected = bs58check.decode(address).slice(1)
}
}
return bufferEquals(actual, expected)
}
module.exports = {
magicHash: magicHash,
sign: sign,
signAsync: signAsync,
verify: verify
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!