Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
'use strict'
const crypto = require('crypto')
const Benchmark = require('benchmark')
const scmpCompare = require('../lib/scmpCompare')
const compareFn = crypto.timingSafeEqual || scmpCompare
// `safe-buffer` in case `Buffer.from` in newer versions of node aren't available
const Buffer = require('safe-buffer').Buffer
const HASH1 = Buffer.from('e727d1464ae12436e899a726da5b2f11d8381b26', 'hex')
const HASH2 = Buffer.from('f727d1464ae12436e899a726da5b2f11d8381b26', 'hex')
const suite = new Benchmark.Suite()
suite.add('crypto check each fn call', function () {
if (crypto.timingSafeEqual) {
return crypto.timingSafeEqual(HASH1, HASH2)
}
return scmpCompare(HASH1, HASH2)
})
.add('crypto check once', function () {
return compareFn(HASH1, HASH2)
})
.on('cycle', function (event) {
console.log(String(event.target))
})
.on('complete', function () {
bytesRead: self.bytesRead,
stubBuffer: self.stubBuffer
}
};
// We got a parse Error fire it off then keep going
self.emit('parseError', errorObject, self);
return;
}
// Ensure that the size of message is larger than 0 and less than the max allowed
if (
sizeOfMessage > 4 &&
sizeOfMessage < self.maxBsonMessageSize &&
sizeOfMessage > data.length
) {
self.buffer = Buffer.alloc(sizeOfMessage);
// Copy all the data into the buffer
data.copy(self.buffer, 0);
// Update bytes read
self.bytesRead = data.length;
// Update sizeOfMessage
self.sizeOfMessage = sizeOfMessage;
// Ensure stub buffer is null
self.stubBuffer = null;
// Exit parsing loop
data = Buffer.alloc(0);
} else if (
sizeOfMessage > 4 &&
sizeOfMessage < self.maxBsonMessageSize &&
sizeOfMessage === data.length
) {
try {
// Check message ID
if (typeof id !== 'number') {
stream.emit('error', new Error('Invalid messageId'))
return false
} else {
length += 2
}
// Check unsubs
if (typeof unsubs === 'object' && unsubs.length) {
for (var i = 0; i < unsubs.length; i += 1) {
if (typeof unsubs[i] !== 'string') {
stream.emit('error', new Error('Invalid unsubscriptions'))
return false
}
length += Buffer.byteLength(unsubs[i]) + 2
}
} else {
stream.emit('error', new Error('Invalid unsubscriptions'))
return false
}
// properies mqtt 5
var propertiesData = null
if (version === 5) {
propertiesData = getProperties(stream, properties)
length += propertiesData.length
}
// Header
stream.write(protocol.UNSUBSCRIBE_HEADER[1][dup ? 1 : 0][0])
// Length
} else {
length += will.payload.length + 2
}
} else {
stream.emit('error', new Error('Invalid will payload'))
return false
}
} else {
length += 2
}
}
// Username
if (username) {
if (username.length) {
length += Buffer.byteLength(username) + 2
} else {
stream.emit('error', new Error('Invalid username'))
return false
}
}
// Password
if (password) {
if (password.length) {
length += byteLength(password) + 2
} else {
stream.emit('error', new Error('Invalid password'))
return false
}
}
static encrypt_with_checksum(private_key, public_key, nonce, message) {
// Warning: Do not put `nonce = ""` in the arguments, in es6 this will not convert "null" into an emtpy string
if (nonce == null)
// null or undefined
nonce = "";
if (!Buffer.isBuffer(message)) {
message = new Buffer(message, "binary");
}
var S = private_key.get_shared_secret(public_key);
// D E B U G
// console.log('encrypt_with_checksum', {
// priv_to_pub: private_key.toPublicKey().toString()
// pub: public_key.toPublicKeyString()
// nonce: nonce
// message: message.length
// S: S.toString('hex')
// })
var aes = Aes.fromSeed(
Buffer.concat([
// A null or empty string nonce will not effect the hash
}
// after the tag code, 2 words are used to store the length (in 5 bit words) of the tag data
// (also left padded, most integers are left padded while buffers are right padded)
tagWords = tagWords.concat([0].concat(intBEToWords(words.length)).slice(-2))
// then append the tag data words
tagWords = tagWords.concat(words)
})
// the data part of the bech32 is TIMESTAMP || TAGS || SIGNATURE
// currently dataWords = TIMESTAMP || TAGS
let dataWords = timestampWords.concat(tagWords)
// the preimage for the signing data is the buffer of the prefix concatenated
// with the buffer conversion of the data words excluding the signature
// (right padded with 0 bits)
let toSign = Buffer.concat([Buffer.from(prefix, 'utf8'), Buffer.from(convert(dataWords, 5, 8))])
// single SHA256 hash for the signature
let payReqHash = sha256(toSign)
// signature is 64 bytes (32 byte r value and 32 byte s value concatenated)
// PLUS one extra byte appended to the right with the recoveryID in [0,1,2,3]
// Then convert to 5 bit words with right padding 0 bits.
let sigWords
if (canReconstruct) {
/* Since BOLT11 does not require a payee_node_key tag in the specs,
most parsers will have to recover the pubkey from the signature
To ensure the tag data has been provided in the right order etc.
we should check that the data we got and the node key given match when
reconstructing a payment request from given signature and recoveryID.
However, if a privatekey is given, the caller is the privkey owner.
Earlier we check if the private key matches the payee node key IF they
gave one. */
_encryptMessage(data, sharedMacData = null) {
const privateKey = util.genPrivateKey();
const x = ecdhX(this._remotePublicKey, privateKey);
const key = concatKDF(x, 32);
const ekey = key.slice(0, 16); // encryption key
const mkey = crypto.createHash('sha256').update(key.slice(16, 32)).digest(); // MAC key
// encrypt
const IV = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-128-ctr', ekey, IV);
const encryptedData = cipher.update(data);
const dataIV = Buffer.concat([IV, encryptedData]);
// create tag
if (!sharedMacData) {
sharedMacData = Buffer.from([]);
}
const tag = crypto.createHmac('sha256', mkey).update(Buffer.concat([dataIV, sharedMacData])).digest();
const publicKey = secp256k1.publicKeyCreate(privateKey, false);
return Buffer.concat([publicKey, dataIV, tag]);
}
const len = Buffer.byteLength(obj)
var buf
if (len < 32) {
buf = Buffer.allocUnsafe(1 + len)
buf[0] = 0xa0 | len
if (len > 0) {
buf.write(obj, 1)
}
} else if (len <= 0xff && !options.compatibilityMode) {
// str8, but only when not in compatibility mode
buf = Buffer.allocUnsafe(2 + len)
buf[0] = 0xd9
buf[1] = len
buf.write(obj, 2)
} else if (len <= 0xffff) {
buf = Buffer.allocUnsafe(3 + len)
buf[0] = 0xda
buf.writeUInt16BE(len, 1)
buf.write(obj, 3)
} else {
buf = Buffer.allocUnsafe(5 + len)
buf[0] = 0xdb
buf.writeUInt32BE(len, 1)
buf.write(obj, 5)
}
return buf
}
var _writeNormal = function(self, data, close, options, callback) {
// If we have a buffer write it using the writeBuffer method
if (Buffer.isBuffer(data)) {
return writeBuffer(self, data, close, callback);
} else {
return writeBuffer(self, Buffer.from(data, 'binary'), close, callback);
}
};
_encryptMessage (data, sharedMacData = null) {
const privateKey = util.genPrivateKey()
const x = ecdhX(this._remotePublicKey, privateKey)
const key = concatKDF(x, 32)
const ekey = key.slice(0, 16) // encryption key
const mkey = crypto.createHash('sha256').update(key.slice(16, 32)).digest() // MAC key
// encrypt
const IV = crypto.randomBytes(16)
const cipher = crypto.createCipheriv('aes-128-ctr', ekey, IV)
const encryptedData = cipher.update(data)
const dataIV = Buffer.concat([ IV, encryptedData ])
// create tag
if (!sharedMacData) {
sharedMacData = Buffer.from([])
}
const tag = crypto.createHmac('sha256', mkey).update(Buffer.concat([dataIV, sharedMacData])).digest()
const publicKey = secp256k1.publicKeyCreate(privateKey, false)
return Buffer.concat([ publicKey, dataIV, tag ])
}