objects.msg
This commit is contained in:
parent
4610701a3e
commit
2e4c91f49b
|
@ -49,7 +49,7 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/
|
|||
- [ ] Object types
|
||||
- [x] getpubkey
|
||||
- [x] pubkey
|
||||
- [ ] msg
|
||||
- [x] msg
|
||||
- [ ] broadcast
|
||||
- [x] WIF
|
||||
- [x] POW
|
||||
|
|
14
lib/_util.js
14
lib/_util.js
|
@ -1,5 +1,5 @@
|
|||
// NOTE(Kagami): End-users shouldn't use this module. While it exports
|
||||
// some helper routines, its API is _not_ stable.
|
||||
// NOTE(Kagami): End-users shouldn't import this module. While it
|
||||
// exports some helper routines, its API is _not_ stable.
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -47,15 +47,15 @@ exports.readTime64BE = function(buf, offset) {
|
|||
return new Date(timestamp * 1000);
|
||||
};
|
||||
|
||||
exports.writeUInt64BE = function(buf, value, offset, noAssert) {
|
||||
function writeUInt64BE(buf, value, offset, noAssert) {
|
||||
buf = buf || new Buffer(8);
|
||||
offset = offset || 0;
|
||||
assert(noAssert || value <= MAX_SAFE_INTEGER, "Unsafe integer");
|
||||
buf.writeUInt32BE(Math.floor(value / 4294967296), offset, noAssert);
|
||||
buf.writeUInt32BE(value % 4294967296, offset + 4, noAssert);
|
||||
return buf;
|
||||
};
|
||||
var writeUInt64BE = exports.writeUInt64BE;
|
||||
}
|
||||
exports.writeUInt64BE = writeUInt64BE;
|
||||
|
||||
exports.writeTime64BE = function(buf, time, offset, noAssert) {
|
||||
var timestamp = Math.floor(time.getTime() / 1000);
|
||||
|
@ -67,8 +67,8 @@ exports.tnow = function() {
|
|||
return Math.floor(time.getTime() / 1000);
|
||||
};
|
||||
|
||||
var DEFAULT_TRIALS_PER_BYTE = 1000;
|
||||
var DEFAULT_EXTRA_BYTES = 1000;
|
||||
var DEFAULT_TRIALS_PER_BYTE = exports.DEFAULT_TRIALS_PER_BYTE = 1000;
|
||||
var DEFAULT_EXTRA_BYTES = exports.DEFAULT_EXTRA_BYTES = 1000;
|
||||
|
||||
exports.getTrials = function(opts) {
|
||||
var nonceTrialsPerByte = opts.nonceTrialsPerByte;
|
||||
|
|
361
lib/objects.js
361
lib/objects.js
|
@ -13,6 +13,7 @@
|
|||
"use strict";
|
||||
|
||||
var objectAssign = Object.assign || require("object-assign");
|
||||
var bufferEqual = require("buffer-equal");
|
||||
var assert = require("./_util").assert;
|
||||
var promise = require("./platform").promise;
|
||||
var bmcrypto = require("./crypto");
|
||||
|
@ -95,8 +96,7 @@ var getpubkey = exports.getpubkey = {
|
|||
assert(decoded.type === object.GETPUBKEY, "Wrong object type");
|
||||
assert(decoded.version >= 2, "getpubkey version is too low");
|
||||
assert(decoded.version <= 4, "getpubkey version is too high");
|
||||
var objectPayload = decoded.objectPayload;
|
||||
delete decoded.objectPayload;
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
if (decoded.version < 4) {
|
||||
assert(objectPayload.length === 20, "getpubkey ripe is too small");
|
||||
// Object payload is copied so it's safe to return it right away.
|
||||
|
@ -148,11 +148,11 @@ var getpubkey = exports.getpubkey = {
|
|||
},
|
||||
};
|
||||
|
||||
// Helper function for `pubkey.decode`.
|
||||
// Extract pubkey data from decrypted object payload.
|
||||
function extractPubkeyV2(buf) {
|
||||
var decoded = {};
|
||||
// Object payload is copied so it's safe to return it right away.
|
||||
function extractPubkey(buf) {
|
||||
var decoded = {length: 132};
|
||||
// We assume here that input buffer was copied before so it's safe to
|
||||
// return reference to it.
|
||||
decoded.behavior = PubkeyBitfield(buf.slice(0, 4));
|
||||
var signPublicKey = decoded.signPublicKey = new Buffer(65);
|
||||
signPublicKey[0] = 4;
|
||||
|
@ -163,23 +163,23 @@ function extractPubkeyV2(buf) {
|
|||
return decoded;
|
||||
}
|
||||
|
||||
// Helper function for `pubkey.decode`.
|
||||
// Extract pubkey data from decrypted object payload.
|
||||
// Extract pubkey version 3 data from decrypted object payload.
|
||||
function extractPubkeyV3(buf) {
|
||||
var decoded = {};
|
||||
var length = 0;
|
||||
var decodedTrials = var_int.decode(buf);
|
||||
var decoded = extractPubkey(buf);
|
||||
var decodedTrials = var_int.decode(buf.slice(132));
|
||||
decoded.nonceTrialsPerByte = decodedTrials.value;
|
||||
length += decodedTrials.length;
|
||||
decoded.length += decodedTrials.length;
|
||||
var decodedExtraBytes = var_int.decode(decodedTrials.rest);
|
||||
decoded.payloadLengthExtraBytes = decodedExtraBytes.value;
|
||||
length += decodedExtraBytes.length;
|
||||
decoded.length += decodedExtraBytes.length;
|
||||
var decodedSigLength = var_int.decode(decodedExtraBytes.rest);
|
||||
decoded.signature = decodedSigLength.rest.slice(0, decodedSigLength.value);
|
||||
var siglen = decodedSigLength.length + decodedSigLength.value;
|
||||
length += siglen;
|
||||
var siglen = decodedSigLength.value;
|
||||
var rest = decodedSigLength.rest;
|
||||
assert(rest.length >= siglen, "Bad pubkey object payload length");
|
||||
decoded.signature = rest.slice(0, siglen);
|
||||
siglen += decodedSigLength.length;
|
||||
decoded._siglen = siglen; // Internal value
|
||||
decoded.length = length;
|
||||
decoded.length += siglen;
|
||||
return decoded;
|
||||
}
|
||||
|
||||
|
@ -213,19 +213,17 @@ var pubkey = exports.pubkey = {
|
|||
* object structure when fulfilled.
|
||||
*/
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve, reject) {
|
||||
return new promise(function(resolve) {
|
||||
opts = opts || {};
|
||||
var neededPubkeys = opts.neededPubkeys || {};
|
||||
var decoded = object.decodePayload(buf);
|
||||
assert(decoded.type === object.PUBKEY, "Wrong object type");
|
||||
var objectPayload = decoded.objectPayload;
|
||||
delete decoded.objectPayload;
|
||||
var version = decoded.version;
|
||||
assert(version >= 2, "Address version is too low");
|
||||
assert(version <= 4, "Address version is too high");
|
||||
var siglen, sig, dataToVerify, pubkeyp;
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
var siglen, pos, sig, dataToVerify, pubkeyp;
|
||||
var addr, addrs, tag, pubkeyEncPrivateKey, dataToDecrypt;
|
||||
var length = 132;
|
||||
|
||||
// v2 pubkey.
|
||||
if (version === 2) {
|
||||
|
@ -233,9 +231,7 @@ var pubkey = exports.pubkey = {
|
|||
assert(
|
||||
objectPayload.length === 132,
|
||||
"Bad pubkey v2 object payload length");
|
||||
objectAssign(decoded, extractPubkeyV2(objectPayload));
|
||||
// Real data length.
|
||||
decoded.length = length;
|
||||
objectAssign(decoded, extractPubkey(objectPayload));
|
||||
return resolve(decoded);
|
||||
}
|
||||
|
||||
|
@ -245,14 +241,11 @@ var pubkey = exports.pubkey = {
|
|||
assert(
|
||||
objectPayload.length >= 135,
|
||||
"Bad pubkey v3 object payload length");
|
||||
objectAssign(decoded, extractPubkeyV2(objectPayload));
|
||||
objectAssign(decoded, extractPubkeyV3(objectPayload.slice(132)));
|
||||
objectAssign(decoded, extractPubkeyV3(objectPayload));
|
||||
siglen = util.popkey(decoded, "_siglen");
|
||||
length += decoded.length;
|
||||
// Real data length.
|
||||
decoded.length = length;
|
||||
// Object message payload without nonce up to sigLength.
|
||||
dataToVerify = buf.slice(8, decoded.headerLength + length - siglen);
|
||||
pos = decoded.headerLength + decoded.length - siglen;
|
||||
// Object message payload from `expiresTime` up to `sig_length`.
|
||||
dataToVerify = buf.slice(8, pos);
|
||||
sig = decoded.signature;
|
||||
pubkeyp = bmcrypto.verify(decoded.signPublicKey, dataToVerify, sig)
|
||||
.then(function() {
|
||||
|
@ -281,30 +274,26 @@ var pubkey = exports.pubkey = {
|
|||
assert(objectPayload.length >= 32, "Bad pubkey v4 object payload length");
|
||||
tag = decoded.tag = objectPayload.slice(0, 32);
|
||||
pubkeyEncPrivateKey = neededPubkeys[tag];
|
||||
if (!pubkeyEncPrivateKey) {
|
||||
return reject(new Error("You are not interested in this pubkey v4"));
|
||||
}
|
||||
assert(pubkeyEncPrivateKey, "You are not interested in this pubkey v4");
|
||||
dataToDecrypt = objectPayload.slice(32);
|
||||
pubkeyp = bmcrypto.decrypt(pubkeyEncPrivateKey, dataToDecrypt)
|
||||
pubkeyp = bmcrypto
|
||||
.decrypt(pubkeyEncPrivateKey, dataToDecrypt)
|
||||
.then(function(decrypted) {
|
||||
// 4 + 64 + 64 + (1+) + (1+) + (1+)
|
||||
assert(
|
||||
decrypted.length >= 135,
|
||||
"Bad pubkey v4 object payload length");
|
||||
objectAssign(decoded, extractPubkeyV2(decrypted));
|
||||
objectAssign(decoded, extractPubkeyV3(decrypted.slice(132)));
|
||||
objectAssign(decoded, extractPubkeyV3(decrypted));
|
||||
siglen = util.popkey(decoded, "_siglen");
|
||||
length += decoded.length;
|
||||
// Real data length.
|
||||
// Since data is encrypted, entire object payload is used.
|
||||
decoded.length = objectPayload.length;
|
||||
dataToVerify = Buffer.concat([
|
||||
// Object header without nonce + tag.
|
||||
buf.slice(8, decoded.headerLength + 32),
|
||||
// Unencrypted pubkey data without signature.
|
||||
decrypted.slice(0, length - siglen),
|
||||
decrypted.slice(0, decoded.length - siglen),
|
||||
]);
|
||||
sig = decoded.signature;
|
||||
// Since data is encrypted, entire object payload is used.
|
||||
decoded.length = objectPayload.length;
|
||||
return bmcrypto.verify(decoded.signPublicKey, dataToVerify, sig);
|
||||
}).then(function() {
|
||||
return decoded;
|
||||
|
@ -420,3 +409,289 @@ var pubkey = exports.pubkey = {
|
|||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Try to decrypt message with all provided identities.
|
||||
function tryDecrypt(identities, buf) {
|
||||
function inner(i) {
|
||||
if (i > last) {
|
||||
return promise.reject("Failed to decrypt msg with given identities");
|
||||
}
|
||||
return bmcrypto
|
||||
.decrypt(identities[i].encPrivateKey, buf)
|
||||
.then(function(decrypted) {
|
||||
return {addr: identities[i], decrypted: decrypted};
|
||||
}).catch(function() {
|
||||
return inner(i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
var last = identities.length - 1;
|
||||
return inner(0);
|
||||
}
|
||||
|
||||
// Loosely decode message in SIMPLE encoding.
|
||||
function decodeSimple(buf) {
|
||||
var decoded = {};
|
||||
var message = buf.toString("utf8");
|
||||
var subject, index;
|
||||
if (message.slice(0, 8) === "Subject:") {
|
||||
subject = message.slice(8);
|
||||
index = subject.indexOf("\nBody:");
|
||||
if (index !== -1) {
|
||||
message = subject.slice(index + 6);
|
||||
subject = subject.slice(0, index);
|
||||
} else {
|
||||
message = "";
|
||||
}
|
||||
decoded.subject = subject;
|
||||
decoded.message = message;
|
||||
} else {
|
||||
decoded.subject = "";
|
||||
decoded.message = message;
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* `msg` object.
|
||||
* @see {@link https://bitmessage.org/wiki/Protocol_specification#msg}
|
||||
* @namespace
|
||||
* @static
|
||||
*/
|
||||
var msg = exports.msg = {
|
||||
/**
|
||||
* Any data with this number may be ignored. The sending node might
|
||||
* simply be sharing its public key with you.
|
||||
*/
|
||||
IGNORE: 0,
|
||||
/**
|
||||
* UTF-8. No 'Subject' or 'Body' sections. Useful for simple strings
|
||||
* of data, like URIs or magnet links.
|
||||
*/
|
||||
TRIVIAL: 1,
|
||||
/**
|
||||
* UTF-8. Uses 'Subject' and 'Body' sections. No MIME is used.
|
||||
*/
|
||||
SIMPLE: 2,
|
||||
|
||||
/**
|
||||
* Decode `msg` object message.
|
||||
* @param {Buffer} buf - Message
|
||||
* @param {?Object} opts - Decoding options
|
||||
* @return {Promise.<Object>} A promise that contains decoded `msg`
|
||||
* 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(msg.decodePayloadAsync(decoded.payload, opts));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Decode `msg` object message payload.
|
||||
* @param {Buffer} buf - Message payload
|
||||
* @param {Object} opts - Decoding options
|
||||
* @return {Promise.<Object>} A promise that contains decoded `msg`
|
||||
* object structure when fulfilled.
|
||||
*/
|
||||
decodePayloadAsync: function(buf, opts) {
|
||||
return new promise(function(resolve) {
|
||||
var decoded = object.decodePayload(buf);
|
||||
assert(decoded.type === object.MSG, "Wrong object type");
|
||||
assert(decoded.version === 1, "Wrong msg version");
|
||||
var objectPayload = util.popkey(decoded, "objectPayload");
|
||||
|
||||
var msgp = tryDecrypt(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 decodedStream = var_int.decode(decodedVersion.rest);
|
||||
decoded.senderStream = decodedStream.value;
|
||||
|
||||
// Behavior, keys.
|
||||
assert(
|
||||
decodedStream.rest.length >= 132,
|
||||
"Bad msg object payload length");
|
||||
objectAssign(decoded, extractPubkey(decodedStream.rest));
|
||||
decoded.length += decodedVersion.length + decodedStream.length;
|
||||
var rest = decrypted.slice(decoded.length);
|
||||
|
||||
// Pow extra.
|
||||
if (decoded.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;
|
||||
}
|
||||
|
||||
// Ripe, encoding.
|
||||
assert(rest.length >= 20, "Bad msg object payload length");
|
||||
decoded.ripe = rest.slice(0, 20);
|
||||
assert(
|
||||
bufferEqual(decoded.ripe, decInfo.addr.ripe),
|
||||
"Message was decrypted but the destination ripe differs");
|
||||
decoded.length += 20;
|
||||
var decodedEncoding = var_int.decode(rest.slice(20));
|
||||
var encoding = decoded.encoding = decodedEncoding.value;
|
||||
decoded.length += decodedEncoding.length;
|
||||
|
||||
// Message.
|
||||
var decodedMsgLength = var_int.decode(decodedEncoding.rest);
|
||||
var msglen = decodedMsgLength.value;
|
||||
rest = decodedMsgLength.rest;
|
||||
assert(rest.length >= msglen, "Bad msg object payload length");
|
||||
decoded.length += decodedMsgLength.length + msglen;
|
||||
var message = rest.slice(0, msglen);
|
||||
if (encoding === msg.TRIVIAL) {
|
||||
decoded.message = message.toString("utf8");
|
||||
} else if (encoding === msg.SIMPLE) {
|
||||
objectAssign(decoded, decodeSimple(message));
|
||||
} else {
|
||||
decoded.message = message;
|
||||
}
|
||||
|
||||
// Acknowledgement data.
|
||||
// TODO(Kagami): Validate ack, check a POW.
|
||||
var decodedAckLength = var_int.decode(rest.slice(msglen));
|
||||
var acklen = decodedAckLength.value;
|
||||
rest = decodedAckLength.rest;
|
||||
assert(rest.length >= acklen, "Bad msg object payload length");
|
||||
decoded.length += decodedAckLength.length + acklen;
|
||||
decoded.ack = rest.slice(0, acklen);
|
||||
|
||||
// Signature.
|
||||
var decodedSigLength = var_int.decode(rest.slice(acklen));
|
||||
var siglen = decodedSigLength.value;
|
||||
rest = decodedSigLength.rest;
|
||||
assert(rest.length >= siglen, "Bad msg object payload length");
|
||||
var sig = decoded.signature = rest.slice(0, siglen);
|
||||
|
||||
// Verify signature.
|
||||
var dataToVerify = Buffer.concat([
|
||||
// Object header without nonce.
|
||||
buf.slice(8, decoded.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(msgp);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Encode `msg` object message.
|
||||
* @param {Object} opts - `msg` object options
|
||||
* @return {Promise.<Buffer>} A promise that contains encoded message
|
||||
* when fulfilled.
|
||||
*/
|
||||
encodeAsync: function(opts) {
|
||||
return msg.encodePayloadAsync(opts).then(function(payload) {
|
||||
return message.encode("object", payload);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Encode `msg` object message payload.
|
||||
* @param {Object} opts - `msg` 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.MSG;
|
||||
opts.version = 1; // The only known msg version
|
||||
var from = Address.decode(opts.from);
|
||||
var to = Address.decode(opts.to);
|
||||
opts.stream = to.stream;
|
||||
var nonceTrialsPerByte, payloadLengthExtraBytes;
|
||||
if (from.version >= 3) {
|
||||
if (opts.friend) {
|
||||
nonceTrialsPerByte = util.DEFAULT_TRIALS_PER_BYTE;
|
||||
payloadLengthExtraBytes = util.DEFAULT_EXTRA_BYTES;
|
||||
} else {
|
||||
nonceTrialsPerByte = util.getTrials(from);
|
||||
payloadLengthExtraBytes = util.getExtraBytes(from);
|
||||
}
|
||||
}
|
||||
var encoding = opts.encoding || msg.TRIVIAL;
|
||||
var message = opts.message;
|
||||
var subject = opts.subject;
|
||||
if (encoding === msg.IGNORE && !message) {
|
||||
// User may omit message for IGNORE encoding.
|
||||
message = new Buffer(0);
|
||||
} else if (!Buffer.isBuffer(message)) {
|
||||
// User may specify message as a string.
|
||||
message = new Buffer(message, "utf8");
|
||||
}
|
||||
if (encoding === msg.SIMPLE && subject) {
|
||||
// User may specify subject for SIMPLE encoding.
|
||||
if (!Buffer.isBuffer(subject)) {
|
||||
subject = new Buffer(subject, "utf8");
|
||||
}
|
||||
message = Buffer.concat([
|
||||
new Buffer("Subject:"),
|
||||
subject,
|
||||
new Buffer("\nBody:"),
|
||||
message,
|
||||
]);
|
||||
}
|
||||
|
||||
// Assembling the unencrypted message data.
|
||||
var msgData = [
|
||||
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) {
|
||||
msgData.push(
|
||||
var_int.encode(nonceTrialsPerByte),
|
||||
var_int.encode(payloadLengthExtraBytes)
|
||||
);
|
||||
}
|
||||
msgData.push(
|
||||
to.ripe,
|
||||
var_int.encode(encoding),
|
||||
var_int.encode(message.length),
|
||||
message
|
||||
);
|
||||
// TODO(Kagami): Calculate ACK.
|
||||
msgData.push(var_int.encode(0));
|
||||
|
||||
opts.objectPayload = new Buffer(0);
|
||||
var obj = object.encodePayloadWithoutNonce(opts);
|
||||
var dataToSign = Buffer.concat([obj].concat(msgData));
|
||||
var msgp = bmcrypto
|
||||
.sign(from.signPrivateKey, dataToSign)
|
||||
.then(function(sig) {
|
||||
var dataToEnc = msgData.concat(var_int.encode(sig.length), sig);
|
||||
dataToEnc = Buffer.concat(dataToEnc);
|
||||
return bmcrypto.encrypt(to.encPublicKey, 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(msgp);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -23,8 +23,8 @@ exports.decode = var_str.decode;
|
|||
/**
|
||||
* Parse raw user agent into software stack list. Most underlying
|
||||
* software comes first.
|
||||
* NOTE: Decoding is rather loose and non-strict, it won't fail on bad
|
||||
* user agent format because it's not that important.
|
||||
* NOTE: Decoding is rather loose, it won't fail on bad user agent
|
||||
* format because it's not that important.
|
||||
* @param {string} str - Raw user agent string
|
||||
* @return {Object[]} Parsed user agent.
|
||||
*/
|
||||
|
|
86
test.js
86
test.js
|
@ -26,6 +26,7 @@ var error = messages.error;
|
|||
var objects = bitmessage.objects;
|
||||
var getpubkey = objects.getpubkey;
|
||||
var pubkey = objects.pubkey;
|
||||
var msg = objects.msg;
|
||||
var WIF = bitmessage.WIF;
|
||||
var POW = bitmessage.POW;
|
||||
var Address = bitmessage.Address;
|
||||
|
@ -91,11 +92,11 @@ describe("Crypto", function() {
|
|||
var privateKey = Buffer(32);
|
||||
privateKey.fill(1);
|
||||
var publicKey = bmcrypto.getPublic(privateKey);
|
||||
var msg = Buffer("test");
|
||||
return bmcrypto.sign(privateKey, msg).then(function(sig) {
|
||||
var message = Buffer("test");
|
||||
return bmcrypto.sign(privateKey, message).then(function(sig) {
|
||||
expect(Buffer.isBuffer(sig)).to.be.true;
|
||||
expect(sig.toString("hex")).to.equal("304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa");
|
||||
return bmcrypto.verify(publicKey, msg, sig);
|
||||
return bmcrypto.verify(publicKey, message, sig);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -495,6 +496,15 @@ describe("Message types", function() {
|
|||
|
||||
// TODO(Kagami): Add tests for encodePayloadAsync/decodePayloadAsync as well.
|
||||
describe("Object types", function() {
|
||||
var signPrivateKey = Buffer("71c95d26c716a5e85e9af9efe26fb5f744dc98005a13d05d23ee92c77e038d9f", "hex");
|
||||
var signPublicKey = bmcrypto.getPublic(signPrivateKey);
|
||||
var encPrivateKey = Buffer("9f9969c93c2d186787a7653f70e49be34c03c4a853e6ad0c867db0946bc433c6", "hex");
|
||||
var encPublicKey = bmcrypto.getPublic(encPrivateKey);
|
||||
var from = Address({
|
||||
signPrivateKey: signPrivateKey,
|
||||
encPrivateKey: encPrivateKey,
|
||||
});
|
||||
|
||||
it("should get type of the encoded object message", function() {
|
||||
var encoded = object.encode({
|
||||
nonce: Buffer(8),
|
||||
|
@ -556,15 +566,6 @@ describe("Object types", function() {
|
|||
});
|
||||
|
||||
describe("pubkey", function() {
|
||||
var signPrivateKey = Buffer("71c95d26c716a5e85e9af9efe26fb5f744dc98005a13d05d23ee92c77e038d9f", "hex");
|
||||
var signPublicKey = bmcrypto.getPublic(signPrivateKey);
|
||||
var encPrivateKey = Buffer("9f9969c93c2d186787a7653f70e49be34c03c4a853e6ad0c867db0946bc433c6", "hex");
|
||||
var encPublicKey = bmcrypto.getPublic(encPrivateKey);
|
||||
var from = Address({
|
||||
signPrivateKey: signPrivateKey,
|
||||
encPrivateKey: encPrivateKey,
|
||||
});
|
||||
|
||||
it("should encode and decode pubkey v2", function() {
|
||||
return pubkey.encodeAsync({
|
||||
ttl: 123,
|
||||
|
@ -627,6 +628,67 @@ describe("Object types", function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("msg", function() {
|
||||
it("should encode and decode msg", function() {
|
||||
return msg.encodeAsync({
|
||||
ttl: 111,
|
||||
from: from,
|
||||
to: from,
|
||||
message: "test",
|
||||
}).then(function(buf) {
|
||||
expect(message.decode(buf).command).to.equal("object");
|
||||
return msg.decodeAsync(buf, {identities: [from]});
|
||||
}).then(function(res) {
|
||||
expect(res.ttl).to.be.at.most(111);
|
||||
expect(res.type).to.equal(object.MSG);
|
||||
expect(res.version).to.equal(1);
|
||||
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(bufferEqual(res.ripe, from.ripe)).to.be.true;
|
||||
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("shouldn't decode msg without identities", function(done) {
|
||||
return msg.encodeAsync({
|
||||
ttl: 111,
|
||||
from: from,
|
||||
to: from,
|
||||
message: "test",
|
||||
}).then(function(buf) {
|
||||
return msg.decodeAsync(buf, {identities: []});
|
||||
}).catch(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should encode and decode SIMPLE msg", function() {
|
||||
return msg.encodeAsync({
|
||||
ttl: 111,
|
||||
from: from,
|
||||
to: from,
|
||||
encoding: msg.SIMPLE,
|
||||
subject: "Тема",
|
||||
message: "Сообщение",
|
||||
}).then(function(buf) {
|
||||
return msg.decodeAsync(buf, {identities: [from]});
|
||||
}).then(function(res) {
|
||||
expect(res.encoding).to.equal(msg.SIMPLE);
|
||||
expect(res.subject).to.equal("Тема");
|
||||
expect(res.message).to.equal("Сообщение");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("WIF", function() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user