objects.broadcast
This commit is contained in:
parent
34868ff014
commit
ea9e8e60ef
|
@ -46,11 +46,11 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
|
|||
- [x] inv
|
||||
- [x] getdata
|
||||
- [x] error
|
||||
- [ ] Object types
|
||||
- [x] Object types
|
||||
- [x] getpubkey
|
||||
- [x] pubkey
|
||||
- [x] msg
|
||||
- [ ] broadcast
|
||||
- [x] broadcast
|
||||
- [x] WIF
|
||||
- [x] POW
|
||||
- [x] High-level classes
|
||||
|
|
|
@ -116,9 +116,19 @@ Address.prototype.getPubkeyPrivateKey = function() {
|
|||
return bmcrypto.sha512(getaddrhash(this)).slice(0, 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the corresponding public key for encryption key used to
|
||||
* encrypt/decrypt {@link pubkey} objects.
|
||||
* @return {Buffer} A 65-byte public key.
|
||||
*/
|
||||
Address.prototype.getPubkeyPublicKey = function() {
|
||||
return bmcrypto.getPublic(this.getPubkeyPrivateKey());
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the encryption key used to encrypt/decrypt
|
||||
* {@link broadcast} objects.
|
||||
* @return {Buffer} A 32-byte private key.
|
||||
*/
|
||||
Address.prototype.getBroadcastPrivateKey = function() {
|
||||
if (this.version >= 4) {
|
||||
|
@ -128,6 +138,15 @@ Address.prototype.getBroadcastPrivateKey = function() {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the corresponding public key for encryption key used to
|
||||
* encrypt/decrypt {@link broadcast} objects.
|
||||
* @return {Buffer} A 65-byte public key.
|
||||
*/
|
||||
Address.prototype.getBroadcastPublicKey = function() {
|
||||
return bmcrypto.getPublic(this.getBroadcastPrivateKey());
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the address tag.
|
||||
* @return {Buffer} A 32-byte address tag.
|
||||
|
|
327
lib/objects.js
327
lib/objects.js
|
@ -183,26 +183,25 @@ function extractPubkeyV3(buf) {
|
|||
return decoded;
|
||||
}
|
||||
|
||||
function findPubkeyPrivateKey(neededPubkeys, tag) {
|
||||
// `neededPubkeys` is either single address or addresses array or
|
||||
// Object key-by-tag. Time to match the tag is O(1), O(n), O(1)
|
||||
// respectfully.
|
||||
neededPubkeys = neededPubkeys || {};
|
||||
var addr, addrs, i;
|
||||
if (Address.isAddress(neededPubkeys)) {
|
||||
addr = neededPubkeys;
|
||||
if (bufferEqual(addr.getTag(), tag)) {
|
||||
return addr.getPubkeyPrivateKey();
|
||||
}
|
||||
} else if (Array.isArray(neededPubkeys)) {
|
||||
addrs = neededPubkeys;
|
||||
// Note that tag matching only works for address version >= 4.
|
||||
function findAddrByTag(addrs, tag) {
|
||||
var i, addr;
|
||||
addrs = addrs || [];
|
||||
if (Address.isAddress(addrs)) {
|
||||
addrs = [addrs];
|
||||
}
|
||||
if (Array.isArray(addrs)) {
|
||||
for (i = 0; i < addrs.length; i++) {
|
||||
if (bufferEqual(addrs[i].getTag(), tag)) {
|
||||
return addrs[i].getPubkeyPrivateKey();
|
||||
addr = addrs[i];
|
||||
if (addr.version >= 4 && bufferEqual(addr.getTag(), tag)) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return neededPubkeys[tag];
|
||||
addr = addrs[tag];
|
||||
if (addr && addr.version >= 4) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,7 +234,7 @@ var pubkey = exports.pubkey = {
|
|||
* @param {?(Address[]|Address|Object)} opts.needed - Address objects
|
||||
* which represent pubkeys that we are interested in. This is used
|
||||
* only for pubkeys v4. `needed` is either single address or addresses
|
||||
* array or Object key-by-tag. Time to match the tag is O(1), O(n),
|
||||
* array or Object addr-by-tag. Time to match the key is O(1), O(n),
|
||||
* O(1) respectfully.
|
||||
* @return {Promise.<Object>} A promise that contains decoded `pubkey`
|
||||
* object structure when fulfilled.
|
||||
|
@ -250,7 +249,7 @@ var pubkey = exports.pubkey = {
|
|||
assert(version <= 4, "Address version is too high");
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
var siglen, pos, sig, dataToVerify, pubkeyp;
|
||||
var tag, pubkeyPrivateKey, dataToDecrypt;
|
||||
var tag, addr, pubkeyPrivateKey, dataToDecrypt;
|
||||
|
||||
// v2 pubkey.
|
||||
if (version === 2) {
|
||||
|
@ -284,8 +283,9 @@ var pubkey = exports.pubkey = {
|
|||
// v4 pubkey.
|
||||
assert(objectPayload.length >= 32, "Bad pubkey v4 object payload length");
|
||||
tag = decoded.tag = objectPayload.slice(0, 32);
|
||||
pubkeyPrivateKey = findPubkeyPrivateKey(opts.needed, tag);
|
||||
assert(pubkeyPrivateKey, "You are not interested in this pubkey v4");
|
||||
addr = findAddrByTag(opts.needed, tag);
|
||||
assert(addr, "You are not interested in this pubkey v4");
|
||||
pubkeyPrivateKey = addr.getPubkeyPrivateKey();
|
||||
dataToDecrypt = objectPayload.slice(32);
|
||||
pubkeyp = bmcrypto
|
||||
.decrypt(pubkeyPrivateKey, dataToDecrypt)
|
||||
|
@ -402,14 +402,12 @@ var pubkey = exports.pubkey = {
|
|||
opts.objectPayload = from.getTag();
|
||||
obj = object.encodePayloadWithoutNonce(opts);
|
||||
var dataToSign = Buffer.concat([obj].concat(pubkeyData));
|
||||
var pubkeyEncPrivateKey = from.getPubkeyPrivateKey();
|
||||
var pubkeyEncPublicKey = bmcrypto.getPublic(pubkeyEncPrivateKey);
|
||||
pubkeyp = bmcrypto
|
||||
.sign(from.signPrivateKey, dataToSign)
|
||||
.then(function(sig) {
|
||||
var dataToEnc = pubkeyData.concat(var_int.encode(sig.length), sig);
|
||||
dataToEnc = Buffer.concat(dataToEnc);
|
||||
return bmcrypto.encrypt(pubkeyEncPublicKey, dataToEnc);
|
||||
return bmcrypto.encrypt(from.getPubkeyPublicKey(), dataToEnc);
|
||||
}).then(function(enc) {
|
||||
// POW calculation here.
|
||||
var nonce = new Buffer(8);
|
||||
|
@ -425,7 +423,8 @@ var pubkey = exports.pubkey = {
|
|||
function tryDecryptMsg(identities, buf) {
|
||||
function inner(i) {
|
||||
if (i > last) {
|
||||
return promise.reject("Failed to decrypt msg with given identities");
|
||||
var err = new Error("Failed to decrypt msg with given identities");
|
||||
return promise.reject(err);
|
||||
}
|
||||
return bmcrypto
|
||||
.decrypt(identities[i].encPrivateKey, buf)
|
||||
|
@ -436,6 +435,9 @@ function tryDecryptMsg(identities, buf) {
|
|||
});
|
||||
}
|
||||
|
||||
if (Address.isAddress(identities)) {
|
||||
identities = [identities];
|
||||
}
|
||||
var last = identities.length - 1;
|
||||
return inner(0);
|
||||
}
|
||||
|
@ -546,23 +548,20 @@ var msg = exports.msg = {
|
|||
*/
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var identities = opts.identities;
|
||||
if (Address.isAddress(identities)) {
|
||||
identities = [identities];
|
||||
}
|
||||
var decoded = object.decodePayload(buf);
|
||||
assert(decoded.type === object.MSG, "Bad object type");
|
||||
assert(decoded.version === 1, "Bad msg version");
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
|
||||
var msgp = tryDecryptMsg(identities, objectPayload)
|
||||
var msgp = tryDecryptMsg(opts.identities, objectPayload)
|
||||
.then(function(decInfo) {
|
||||
var decrypted = decInfo.decrypted;
|
||||
|
||||
// Version, stream.
|
||||
// TODO(Kagami): Validate version range?
|
||||
var decodedVersion = var_int.decode(decrypted);
|
||||
decoded.senderVersion = decodedVersion.value;
|
||||
var senderVersion = decoded.senderVersion = decodedVersion.value;
|
||||
assert(senderVersion >= 2, "Sender version is too low");
|
||||
assert(senderVersion <= 4, "Sender version is too high");
|
||||
var decodedStream = var_int.decode(decodedVersion.rest);
|
||||
decoded.senderStream = decodedStream.value;
|
||||
|
||||
|
@ -588,9 +587,11 @@ var msg = exports.msg = {
|
|||
// Ripe, encoding.
|
||||
assert(rest.length >= 20, "Bad msg object payload length");
|
||||
decoded.ripe = rest.slice(0, 20);
|
||||
// TODO(Kagami): Also check against the calculatedRipe (see
|
||||
// GH-6)?
|
||||
assert(
|
||||
bufferEqual(decoded.ripe, decInfo.addr.ripe),
|
||||
"msg was decrypted but the destination ripe differs");
|
||||
"msg was decrypted but the destination ripe doesn't match");
|
||||
decoded.length += 20;
|
||||
var decodedEncoding = var_int.decode(rest.slice(20));
|
||||
var encoding = decoded.encoding = decodedEncoding.value;
|
||||
|
@ -664,6 +665,8 @@ var msg = exports.msg = {
|
|||
opts.type = object.MSG;
|
||||
opts.version = 1; // The only known msg version
|
||||
var from = Address.decode(opts.from);
|
||||
assert(from.version >= 2, "Address version is too low");
|
||||
assert(from.version <= 4, "Address version is too high");
|
||||
var to = Address.decode(opts.to);
|
||||
opts.stream = to.stream;
|
||||
var nonceTrialsPerByte, payloadLengthExtraBytes;
|
||||
|
@ -724,3 +727,263 @@ var msg = exports.msg = {
|
|||
};
|
||||
|
||||
var DEFAULT_ENCODING = msg.TRIVIAL;
|
||||
|
||||
// Try to decrypt broadcast v4 with all provided subscription objects.
|
||||
function tryDecryptBroadcastV4(subscriptions, buf) {
|
||||
function inner(i) {
|
||||
if (i > last) {
|
||||
var err = new Error("Failed to decrypt msg with given identities");
|
||||
return promise.reject(err);
|
||||
}
|
||||
return bmcrypto
|
||||
.decrypt(subscriptions[i].getBroadcastPrivateKey(), buf)
|
||||
.then(function(decrypted) {
|
||||
return {addr: subscriptions[i], decrypted: decrypted};
|
||||
}).catch(function() {
|
||||
return inner(i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
if (Address.isAddress(subscriptions)) {
|
||||
subscriptions = [subscriptions];
|
||||
} else if (!Array.isArray(subscriptions)) {
|
||||
subscriptions = Object.keys(subscriptions).map(function(k) {
|
||||
return subscriptions[k];
|
||||
});
|
||||
}
|
||||
// Only addresses with version < 4 may be used to encode broadcast v4.
|
||||
subscriptions = subscriptions.filter(function(a) {
|
||||
return a.version < 4;
|
||||
});
|
||||
var last = subscriptions.length - 1;
|
||||
return inner(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* `broadcast` object.
|
||||
* @see {@link https://bitmessage.org/wiki/Protocol_specification#broadcast}
|
||||
* @namespace
|
||||
* @static
|
||||
*/
|
||||
var broadcast = exports.broadcast = {
|
||||
/**
|
||||
* Decode `broadcast` object message.
|
||||
* @param {Buffer} buf - Message
|
||||
* @param {?Object} opts - Decoding options
|
||||
* @return {Promise.<Object>} A promise that contains decoded
|
||||
* `broadcast` object structure when fulfilled.
|
||||
*/
|
||||
decodeAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = message.decode(buf);
|
||||
assert(decoded.command === "object", "Bad command");
|
||||
resolve(broadcast.decodePayloadAsync(decoded.payload, opts));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Decode `broadcast` object message payload.
|
||||
* @param {Buffer} buf - Message payload
|
||||
* @param {Object} opts - Decoding options
|
||||
* @param {(Address[]|Address|Object)} opts.subscriptions - Address
|
||||
* objects which represent broadcast subscriptions. `subscriptions` is
|
||||
* either single address or addresses array or Object
|
||||
* addr-by-tag/addr-by-ripe. Time to match the key is O(1), O(n), O(1)
|
||||
* respectfully.
|
||||
* @return {Promise.<Object>} A promise that contains decoded `pubkey`
|
||||
* object structure when fulfilled.
|
||||
*/
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = object.decodePayload(buf);
|
||||
assert(decoded.type === object.BROADCAST, "Bad object type");
|
||||
var version = decoded.version;
|
||||
assert(version === 4 || version === 5, "Bad broadcast version");
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
var tag, addr, broadPrivateKey, dataToDecrypt, broadp;
|
||||
|
||||
if (version === 4) {
|
||||
broadp = tryDecryptBroadcastV4(opts.subscriptions, objectPayload);
|
||||
} else {
|
||||
assert(
|
||||
objectPayload.length >= 32,
|
||||
"Bad broadcast v5 object payload length");
|
||||
tag = decoded.tag = objectPayload.slice(0, 32);
|
||||
addr = findAddrByTag(opts.subscriptions, tag);
|
||||
assert(addr, "You are not interested in this broadcast v5");
|
||||
broadPrivateKey = addr.getBroadcastPrivateKey();
|
||||
dataToDecrypt = objectPayload.slice(32);
|
||||
broadp = bmcrypto
|
||||
.decrypt(broadPrivateKey, dataToDecrypt)
|
||||
.then(function(decrypted) {
|
||||
return {addr: addr, decrypted: decrypted};
|
||||
});
|
||||
}
|
||||
|
||||
broadp = broadp.then(function(decInfo) {
|
||||
var decrypted = decInfo.decrypted;
|
||||
|
||||
// Version, stream.
|
||||
var decodedVersion = var_int.decode(decrypted);
|
||||
var senderVersion = decoded.senderVersion = decodedVersion.value;
|
||||
if (version === 4) {
|
||||
assert(senderVersion >= 2, "Sender version is too low");
|
||||
assert(senderVersion <= 3, "Sender version is too high");
|
||||
} else {
|
||||
assert(senderVersion === 4, "Bad sender version");
|
||||
}
|
||||
var decodedStream = var_int.decode(decodedVersion.rest);
|
||||
var senderStream = decoded.senderStream = decodedStream.value;
|
||||
assert(
|
||||
senderStream === decoded.stream,
|
||||
"Cleartext broadcast object stream doesn't match encrypted");
|
||||
|
||||
// Behavior, keys.
|
||||
assert(
|
||||
decodedStream.rest.length >= 132,
|
||||
"Bad broadcast object payload length");
|
||||
objectAssign(decoded, extractPubkey(decodedStream.rest));
|
||||
decoded.length += decodedVersion.length + decodedStream.length;
|
||||
var rest = decrypted.slice(decoded.length);
|
||||
var sender = new Address({
|
||||
version: senderVersion,
|
||||
stream: senderStream,
|
||||
signPublicKey: decoded.signPublicKey,
|
||||
encPublicKey: decoded.encPublicKey,
|
||||
});
|
||||
if (version === 4) {
|
||||
assert(
|
||||
bufferEqual(sender.ripe, decInfo.addr.ripe),
|
||||
"The keys used to encrypt the broadcast doesn't match the keys "+
|
||||
"embedded into the object");
|
||||
} else {
|
||||
assert(
|
||||
bufferEqual(sender.getTag(), tag),
|
||||
"The tag used to encrypt the broadcast doesn't match the keys "+
|
||||
"and version/stream embedded into the object");
|
||||
}
|
||||
|
||||
// Pow extra.
|
||||
if (senderVersion >= 3) {
|
||||
var decodedTrials = var_int.decode(rest);
|
||||
decoded.nonceTrialsPerByte = decodedTrials.value;
|
||||
decoded.length += decodedTrials.length;
|
||||
var decodedExtraBytes = var_int.decode(decodedTrials.rest);
|
||||
decoded.payloadLengthExtraBytes = decodedExtraBytes.value;
|
||||
decoded.length += decodedExtraBytes.length;
|
||||
rest = decodedExtraBytes.rest;
|
||||
}
|
||||
|
||||
// Encoding, message
|
||||
var decodedEncoding = var_int.decode(rest);
|
||||
var encoding = decoded.encoding = decodedEncoding.value;
|
||||
decoded.length += decodedEncoding.length;
|
||||
var decodedMsgLength = var_int.decode(decodedEncoding.rest);
|
||||
var msglen = decodedMsgLength.value;
|
||||
rest = decodedMsgLength.rest;
|
||||
assert(rest.length >= msglen, "Bad broadcast object payload length");
|
||||
decoded.length += decodedMsgLength.length + msglen;
|
||||
var message = rest.slice(0, msglen);
|
||||
objectAssign(decoded, decodeMessage(message, encoding));
|
||||
|
||||
// Signature.
|
||||
var decodedSigLength = var_int.decode(rest.slice(msglen));
|
||||
var siglen = decodedSigLength.value;
|
||||
rest = decodedSigLength.rest;
|
||||
assert(rest.length >= siglen, "Bad broadcast object payload length");
|
||||
var sig = decoded.signature = rest.slice(0, siglen);
|
||||
|
||||
// Verify signature.
|
||||
var headerLength = decoded.headerLength;
|
||||
if (version !== 4) {
|
||||
// Compensate for tag.
|
||||
headerLength += 32;
|
||||
}
|
||||
var dataToVerify = Buffer.concat([
|
||||
// Object header without nonce.
|
||||
buf.slice(8, headerLength),
|
||||
// Unencrypted pubkey data without signature.
|
||||
decrypted.slice(0, decoded.length),
|
||||
]);
|
||||
// Since data is encrypted, entire object payload is used.
|
||||
decoded.length = objectPayload.length;
|
||||
return bmcrypto.verify(decoded.signPublicKey, dataToVerify, sig);
|
||||
}).then(function() {
|
||||
return decoded;
|
||||
});
|
||||
resolve(broadp);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Encode `broadcast` object message.
|
||||
* @param {Object} opts - `broadcast` object options
|
||||
* @return {Promise.<Buffer>} A promise that contains encoded message
|
||||
* when fulfilled.
|
||||
*/
|
||||
encodeAsync: function(opts) {
|
||||
return broadcast.encodePayloadAsync(opts).then(function(payload) {
|
||||
return message.encode("object", payload);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Encode `broadcast` object message payload.
|
||||
* @param {Object} opts - `broadcast` object options
|
||||
* @return {Promise.<Buffer>} A promise that contains encoded message
|
||||
* payload when fulfilled.
|
||||
*/
|
||||
// FIXME(Kagami): Do a POW.
|
||||
encodePayloadAsync: function(opts) {
|
||||
return new promise(function(resolve) {
|
||||
// Deal with options.
|
||||
opts = objectAssign({}, opts);
|
||||
opts.type = object.BROADCAST;
|
||||
var from = Address.decode(opts.from);
|
||||
assert(from.version >= 2, "Address version is too low");
|
||||
assert(from.version <= 4, "Address version is too high");
|
||||
opts.version = from.version >= 4 ? 5 : 4;
|
||||
opts.stream = from.stream;
|
||||
var encoding = opts.encoding || DEFAULT_ENCODING;
|
||||
var message = encodeMessage(opts);
|
||||
|
||||
// Assemble the unencrypted message data.
|
||||
var broadData = [
|
||||
var_int.encode(from.version),
|
||||
var_int.encode(from.stream),
|
||||
from.behavior.buffer,
|
||||
from.signPublicKey.slice(1),
|
||||
from.encPublicKey.slice(1),
|
||||
];
|
||||
if (from.version >= 3) {
|
||||
broadData.push(
|
||||
var_int.encode(util.getTrials(from)),
|
||||
var_int.encode(util.getExtraBytes(from))
|
||||
);
|
||||
}
|
||||
broadData.push(
|
||||
var_int.encode(encoding),
|
||||
var_int.encode(message.length),
|
||||
message
|
||||
);
|
||||
|
||||
// Sign and encrypt.
|
||||
opts.objectPayload = from.version >= 4 ? from.getTag() : new Buffer(0);
|
||||
var obj = object.encodePayloadWithoutNonce(opts);
|
||||
var dataToSign = Buffer.concat([obj].concat(broadData));
|
||||
var broadp = bmcrypto
|
||||
.sign(from.signPrivateKey, dataToSign)
|
||||
.then(function(sig) {
|
||||
var dataToEnc = broadData.concat(var_int.encode(sig.length), sig);
|
||||
dataToEnc = Buffer.concat(dataToEnc);
|
||||
return bmcrypto.encrypt(from.getBroadcastPublicKey(), dataToEnc);
|
||||
}).then(function(enc) {
|
||||
// POW calculation here.
|
||||
var nonce = new Buffer(8);
|
||||
// Concat object header with ecnrypted data and we are done.
|
||||
return Buffer.concat([nonce, obj, enc]);
|
||||
});
|
||||
resolve(broadp);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
97
test.js
97
test.js
|
@ -27,6 +27,7 @@ var objects = bitmessage.objects;
|
|||
var getpubkey = objects.getpubkey;
|
||||
var pubkey = objects.pubkey;
|
||||
var msg = objects.msg;
|
||||
var broadcast = objects.broadcast;
|
||||
var WIF = bitmessage.WIF;
|
||||
var POW = bitmessage.POW;
|
||||
var Address = bitmessage.Address;
|
||||
|
@ -504,6 +505,11 @@ describe("Object types", function() {
|
|||
signPrivateKey: signPrivateKey,
|
||||
encPrivateKey: encPrivateKey,
|
||||
});
|
||||
var fromV3 = Address({
|
||||
version: 3,
|
||||
signPrivateKey: signPrivateKey,
|
||||
encPrivateKey: encPrivateKey,
|
||||
});
|
||||
|
||||
it("should get type of the encoded object message", function() {
|
||||
var encoded = object.encode({
|
||||
|
@ -689,6 +695,74 @@ describe("Object types", function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("broadcast", function() {
|
||||
it("should encode and decode broadcast v4", function() {
|
||||
return broadcast.encodeAsync({
|
||||
ttl: 987,
|
||||
from: fromV3,
|
||||
message: "test",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return broadcast.decodeAsync(buf, {subscriptions: fromV3});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(987);
|
||||
expect(res.type).to.equal(object.BROADCAST);
|
||||
expect(res.version).to.equal(4);
|
||||
expect(res.stream).to.equal(1);
|
||||
expect(res.senderVersion).to.equal(3);
|
||||
expect(res.senderStream).to.equal(1);
|
||||
expect(res.behavior.get(PubkeyBitfield.DOES_ACK)).to.be.true;
|
||||
expect(bufferEqual(res.signPublicKey, signPublicKey)).to.be.true;
|
||||
expect(bufferEqual(res.encPublicKey, encPublicKey)).to.be.true;
|
||||
expect(res.nonceTrialsPerByte).to.equal(1000);
|
||||
expect(res.payloadLengthExtraBytes).to.equal(1000);
|
||||
expect(res.encoding).to.equal(msg.TRIVIAL);
|
||||
expect(res.message).to.equal("test");
|
||||
expect(res).to.not.have.property("subject");
|
||||
expect(Buffer.isBuffer(res.signature)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it("should encode and decode broadcast v5", function() {
|
||||
return broadcast.encodeAsync({
|
||||
ttl: 101,
|
||||
from: from,
|
||||
message: "キタ━━━(゜∀゜)━━━!!!!!",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return broadcast.decodeAsync(buf, {subscriptions: [from]});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(987);
|
||||
expect(res.type).to.equal(object.BROADCAST);
|
||||
expect(res.version).to.equal(5);
|
||||
expect(res.stream).to.equal(1);
|
||||
expect(res.senderVersion).to.equal(4);
|
||||
expect(res.senderStream).to.equal(1);
|
||||
expect(res.behavior.get(PubkeyBitfield.DOES_ACK)).to.be.true;
|
||||
expect(bufferEqual(res.signPublicKey, signPublicKey)).to.be.true;
|
||||
expect(bufferEqual(res.encPublicKey, encPublicKey)).to.be.true;
|
||||
expect(res.nonceTrialsPerByte).to.equal(1000);
|
||||
expect(res.payloadLengthExtraBytes).to.equal(1000);
|
||||
expect(res.encoding).to.equal(msg.TRIVIAL);
|
||||
expect(res.message).to.equal("キタ━━━(゜∀゜)━━━!!!!!");
|
||||
expect(res).to.not.have.property("subject");
|
||||
expect(Buffer.isBuffer(res.signature)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it("shouldn't decode broadcast without subscriptions", function(done) {
|
||||
return broadcast.encodeAsync({
|
||||
ttl: 101,
|
||||
from: from,
|
||||
message: "test",
|
||||
}).then(function(buf) {
|
||||
return broadcast.decodeAsync(buf, {subscriptions: [fromV3]});
|
||||
}).catch(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("WIF", function() {
|
||||
|
@ -825,23 +899,40 @@ describe("High-level classes", function() {
|
|||
expect(addr.getTag().toString("hex")).to.equal("facf1e3e6c74916203b7f714ca100d4d60604f0917696d0f09330f82f52bed1a");
|
||||
});
|
||||
|
||||
it("should calculate a private key to encrypt pubkey object", function() {
|
||||
it("should calculate a private key to decrypt pubkey object", function() {
|
||||
var addr = Address.decode("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z");
|
||||
expect(addr.getPubkeyPrivateKey().toString("hex")).to.equal("15e516173769dc87d4a8e8ed90200362fa58c0228bb2b70b06f26c089a9823a4");
|
||||
});
|
||||
|
||||
it("should calculate a private key to encrypt broadcast v4", function() {
|
||||
it("should calculate a public key to encrypt pubkey object", function() {
|
||||
var addr = Address.decode("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z");
|
||||
expect(addr.getPubkeyPublicKey().toString("hex")).to.equal("04ee196be97db61886beeec9ebc2c28b7d4cafbc407c31d8aac2f867068f727874e2d305ba970bd09a951aa2cde52b66061a5a8e709cda1125635a97e1c7b85ab4");
|
||||
});
|
||||
|
||||
it("should calculate a private key to decrypt broadcast v4", function() {
|
||||
var addr = Address.decode(" 2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU ");
|
||||
expect(addr.version).to.equal(3);
|
||||
expect(addr.getBroadcastPrivateKey().toString("hex")).to.equal("664420eaed1b6b3208fc04905c2f6ca758594c537eb5a08f2f0c2bbe6f07fb44");
|
||||
});
|
||||
|
||||
it("should calculate a private key to encrypt broadcast v5", function() {
|
||||
it("should calculate a public key to encrypt broadcast v4", function() {
|
||||
var addr = Address.decode(" 2D8Jxw5yiepaQqxrx43iPPNfRqbvWoJLoU ");
|
||||
expect(addr.version).to.equal(3);
|
||||
expect(addr.getBroadcastPublicKey().toString("hex")).to.equal("04da633350cf2ef8194b83ae028555971df56a64948940693e54b8b4c2597b8f9e833ac1285b37487121c271346fb29684e723a992aeb37b20962406ccade6c8d3");
|
||||
});
|
||||
|
||||
it("should calculate a private key to decrypt broadcast v5", function() {
|
||||
var addr = Address.decode("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z");
|
||||
expect(addr.version).to.equal(4);
|
||||
expect(addr.getBroadcastPrivateKey().toString("hex")).to.equal("15e516173769dc87d4a8e8ed90200362fa58c0228bb2b70b06f26c089a9823a4");
|
||||
});
|
||||
|
||||
it("should calculate a public key to encrypt broadcast v5", function() {
|
||||
var addr = Address.decode("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z");
|
||||
expect(addr.version).to.equal(4);
|
||||
expect(addr.getBroadcastPublicKey().toString("hex")).to.equal("04ee196be97db61886beeec9ebc2c28b7d4cafbc407c31d8aac2f867068f727874e2d305ba970bd09a951aa2cde52b66061a5a8e709cda1125635a97e1c7b85ab4");
|
||||
});
|
||||
|
||||
it("should allow to decode Address instance", function() {
|
||||
var addr = Address.decode("2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z");
|
||||
expect(addr.ripe.toString("hex")).to.equal("003ab6655de4bd8c603eba9b00dd5970725fdd56");
|
||||
|
|
Loading…
Reference in New Issue
Block a user