Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bitcoinjs-message

Package Overview
Dependencies
Maintainers
4
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitcoinjs-message - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

1

CHANGELOG.md
# 2.0.0
__breaking__
- `messagePrefix` is now the last parameter for the `sign`, `verify` and `magicHash` functions
- `messagePrefix` is now defaulted to the Bitcoin network message prefix

@@ -1,9 +0,17 @@

var bs58check = require('bs58check')
var bufferEquals = require('buffer-equals')
var createHash = require('create-hash')
var secp256k1 = require('secp256k1')
var varuint = require('varuint-bitcoin')
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()
return createHash('sha256')
.update(b)
.digest()
}

@@ -14,7 +22,14 @@ function hash256 (buffer) {

function hash160 (buffer) {
return createHash('ripemd160').update(sha256(buffer)).digest()
return createHash('ripemd160')
.update(sha256(buffer))
.digest()
}
function encodeSignature (signature, recovery, compressed) {
if (compressed) recovery += 4
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])

@@ -26,7 +41,14 @@ }

var flagByte = buffer.readUInt8(0) - 27
if (flagByte > 7) throw new Error('Invalid signature parameter')
const flagByte = buffer.readUInt8(0) - 27
if (flagByte > 15 || flagByte < 0) {
throw new Error('Invalid signature parameter')
}
return {
compressed: !!(flagByte & 4),
compressed: !!(flagByte & 12),
segwitType: !(flagByte & 8)
? null
: !(flagByte & 4)
? SEGWIT_TYPES.P2SH_P2WPKH
: SEGWIT_TYPES.P2WPKH,
recovery: flagByte & 3,

@@ -39,6 +61,10 @@ signature: buffer.slice(1)

messagePrefix = messagePrefix || '\u0018Bitcoin Signed Message:\n'
if (!Buffer.isBuffer(messagePrefix)) messagePrefix = Buffer.from(messagePrefix, 'utf8')
if (!Buffer.isBuffer(messagePrefix)) {
messagePrefix = Buffer.from(messagePrefix, 'utf8')
}
var messageVISize = varuint.encodingLength(message.length)
var buffer = Buffer.allocUnsafe(messagePrefix.length + messageVISize + message.length)
const messageVISize = varuint.encodingLength(message.length)
const buffer = Buffer.allocUnsafe(
messagePrefix.length + messageVISize + message.length
)
messagePrefix.copy(buffer, 0)

@@ -50,6 +76,41 @@ varuint.encode(message.length, buffer, messagePrefix.length)

function sign (message, privateKey, compressed, messagePrefix) {
var hash = magicHash(message, messagePrefix)
var sigObj = secp256k1.sign(hash, privateKey)
return encodeSignature(sigObj.signature, sigObj.recovery, compressed)
function sign (
message,
privateKey,
compressed,
messagePrefix,
sigOptions
) {
if (typeof messagePrefix === 'object' && sigOptions === undefined) {
sigOptions = messagePrefix
messagePrefix = 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 +
'"'
)
}
const hash = magicHash(message, messagePrefix)
const sigObj = secp256k1.sign(hash, privateKey, { data: extraEntropy })
return encodeSignature(
sigObj.signature,
sigObj.recovery,
compressed,
segwitType
)
}

@@ -60,8 +121,32 @@

var parsed = decodeSignature(signature)
var hash = magicHash(message, messagePrefix)
var publicKey = secp256k1.recover(hash, parsed.signature, parsed.recovery, parsed.compressed)
const parsed = decodeSignature(signature)
const hash = magicHash(message, messagePrefix)
const publicKey = secp256k1.recover(
hash,
parsed.signature,
parsed.recovery,
parsed.compressed
)
const publicKeyHash = hash160(publicKey)
let actual, expected
var actual = hash160(publicKey)
var expected = bs58check.decode(address).slice(1)
if (parsed.segwitType) {
if (parsed.segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
const redeemScript = Buffer.concat([
Buffer.from('0014', 'hex'),
publicKeyHash
])
const redeemScriptHash = hash160(redeemScript)
actual = redeemScriptHash
expected = bs58check.decode(address).slice(1)
} else if (parsed.segwitType === SEGWIT_TYPES.P2WPKH) {
const result = bech32.decode(address)
const data = bech32.fromWords(result.words.slice(1))
actual = publicKeyHash
expected = Buffer.from(data)
}
} else {
actual = publicKeyHash
expected = bs58check.decode(address).slice(1)
}

@@ -68,0 +153,0 @@ return bufferEquals(actual, expected)

9

package.json
{
"name": "bitcoinjs-message",
"version": "2.0.0",
"version": "2.1.0",
"description": "bitcoinjs-message",

@@ -30,3 +30,4 @@ "keywords": [

"dependencies": {
"bs58check": "^2.0.2",
"bech32": "^1.1.3",
"bs58check": "^2.1.2",
"buffer-equals": "^1.0.3",

@@ -40,4 +41,4 @@ "create-hash": "^1.1.2",

"bitcoinjs-lib": "^3.2.0",
"nyc": "^11.2.1",
"standard": "*",
"nyc": "^14.1.1",
"standard": "^12.0.1",
"tape": "^4.5.1"

@@ -44,0 +45,0 @@ },

@@ -15,3 +15,7 @@ # bitcoinjs-message

> sign(message, privateKey, compressed[, network.messagePrefix])
> sign(message, privateKey, compressed[, network.messagePrefix, sigOptions])
> - If you pass the sigOptions arg instead of messagePrefix it will dynamically replace.
> - sigOptions contains two attributes
> - `segwitType` should be one of `'p2sh(p2wpkh)'` or `'p2wpkh'`
> - `extraEntropy` will be used to create non-deterministic signatures using the RFC6979 extra entropy parameter. R value reuse is not an issue.

@@ -21,3 +25,3 @@ Sign a Bitcoin message

var keyPair = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
var privateKey = keyPair.d.toBuffer(32)
var privateKey = keyPair.privateKey
var message = 'This is an example of a signed message.'

@@ -30,2 +34,27 @@

To produce non-deterministic signatures you can pass an extra option to sign()
``` javascript
var { randomBytes } = require('crypto')
var keyPair = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
var privateKey = keyPair.privateKey
var message = 'This is an example of a signed message.'
var signature = bitcoinMessage.sign(message, privateKey, keyPair.compressed, { extraEntropy: randomBytes(32) })
console.log(signature.toString('base64'))
// => different (but valid) signature each time
```
Sign a Bitcoin message (with segwit addresses)
``` javascript
// P2SH(P2WPKH) address 'p2sh(p2wpkh)'
var signature = bitcoinMessage.sign(message, privateKey, keyPair.compressed, { segwitType: 'p2sh(p2wpkh)' })
console.log(signature.toString('base64'))
// => 'I9L5yLFjti0QTHhPyFrZCT1V/MMnBtXKmoiKDZ78NDBjERki6ZTQZdSMCtkgoNmp17By9ItJr8o7ChX0XxY91nk='
// P2WPKH address 'p2wpkh'
var signature = bitcoinMessage.sign(message, privateKey, keyPair.compressed, { segwitType: 'p2wpkh' })
console.log(signature.toString('base64'))
// => 'J9L5yLFjti0QTHhPyFrZCT1V/MMnBtXKmoiKDZ78NDBjERki6ZTQZdSMCtkgoNmp17By9ItJr8o7ChX0XxY91nk='
```
> verify(message, address, signature[, network.messagePrefix])

@@ -36,4 +65,2 @@

var address = '1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN'
var signature = 'HJLQlDWLyb1Ef8bQKEISzFbDAKctIlaqOpGbrk3YVtRsjmC61lpE5ErkPRUFtDKtx98vHFGUWlFhsh3DiW6N0rE'
var message = 'This is an example of a signed message.'

@@ -40,0 +67,0 @@ console.log(bitcoinMessage.verify(message, address, signature))

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc