Add additional functions:

encodePublic(publicKey), decodePublic(publicKey) used in
encrypt() and decrypt() respectively - to comply with the network.

Minor formatting change.
This commit is contained in:
Lee Miller 2022-12-25 00:20:37 +02:00
parent e868b2c34f
commit 37b79ccde1
Signed by: lee.miller
GPG Key ID: 4F97A5EA88F4AB63

View File

@ -5,12 +5,15 @@
"use strict"; "use strict";
const EC_GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex'); const EC_GROUP_ORDER = Buffer.from(
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex');
const ZERO32 = Buffer.alloc(32, 0); const ZERO32 = Buffer.alloc(32, 0);
const curve_secp256k1 = 714,
key_length = 32;
var promise = typeof Promise === "undefined" ? var promise = typeof Promise === "undefined" ?
require("es6-promise").Promise : require("es6-promise").Promise : Promise;
Promise;
var crypto = require("crypto"); var crypto = require("crypto");
// try to use secp256k1, fallback to browser implementation // try to use secp256k1, fallback to browser implementation
try { try {
@ -25,7 +28,7 @@ try {
} }
} }
function isScalar (x) { function isScalar(x) {
return Buffer.isBuffer(x) && x.length === 32; return Buffer.isBuffer(x) && x.length === 32;
} }
@ -117,6 +120,29 @@ var getPublic = exports.getPublic = function(privateKey) {
return secp256k1.publicKeyConvert(compressed, false); return secp256k1.publicKeyConvert(compressed, false);
}; };
// to comply with the bitmessage network
function encodePublic(publicKey) {
assert(publicKey.length === 65, "Bad public key");
var buf = Buffer.alloc(70);
buf.writeUInt16BE(curve_secp256k1, 0, true);
buf.writeUInt16BE(key_length, 2, true);
publicKey.copy(buf, 4, 1, 33);
buf.writeUInt16BE(key_length, 36, true);
publicKey.copy(buf, 38, 33, 65);
return buf;
}
function decodePublic(publicKey) {
assert(publicKey.readUInt16BE(0, true) === curve_secp256k1, "Wrong curve!");
assert(publicKey.readUInt16BE(2, true) === key_length, "Bad key length!");
assert(publicKey.readUInt16BE(36, true) === key_length, "Bad key length!");
var buf = Buffer.alloc(65);
buf[0] = 0x04;
publicKey.copy(buf, 1, 4, 36);
publicKey.copy(buf, 33, 38, 70);
return buf;
}
/** /**
* Get compressed version of public key. * Get compressed version of public key.
*/ */
@ -213,7 +239,7 @@ exports.encrypt = function(publicKeyTo, msg, opts) {
{ {
ephemPrivateKey = opts.ephemPrivateKey || crypto.randomBytes(32); ephemPrivateKey = opts.ephemPrivateKey || crypto.randomBytes(32);
} }
ephemPublicKey = getPublic(ephemPrivateKey); ephemPublicKey = encodePublic(getPublic(ephemPrivateKey));
resolve(derive(ephemPrivateKey, publicKeyTo)); resolve(derive(ephemPrivateKey, publicKeyTo));
}).then(function(Px) { }).then(function(Px) {
var hash = sha512(Px); var hash = sha512(Px);
@ -241,18 +267,20 @@ exports.encrypt = function(publicKeyTo, msg, opts) {
* plaintext on successful decryption and rejects on failure. * plaintext on successful decryption and rejects on failure.
*/ */
exports.decrypt = function(privateKey, opts) { exports.decrypt = function(privateKey, opts) {
return derive(privateKey, opts.ephemPublicKey).then(function(Px) { return derive(
assert(privateKey.length === 32, "Bad private key"); privateKey, decodePublic(opts.ephemPublicKey)).then(function(Px) {
assert(isValidPrivateKey(privateKey), "Bad private key"); assert(privateKey.length === 32, "Bad private key");
var hash = sha512(Px); assert(isValidPrivateKey(privateKey), "Bad private key");
var encryptionKey = hash.slice(0, 32); var hash = sha512(Px);
var macKey = hash.slice(32); var encryptionKey = hash.slice(0, 32);
var dataToMac = Buffer.concat([ var macKey = hash.slice(32);
opts.iv, var dataToMac = Buffer.concat([
opts.ephemPublicKey, opts.iv,
opts.ciphertext opts.ephemPublicKey,
]); opts.ciphertext
var realMac = hmacSha256(macKey, dataToMac); ]);
assert(equalConstTime(opts.mac, realMac), "Bad MAC"); return aes256CbcDecrypt(opts.iv, encryptionKey, opts.ciphertext); var realMac = hmacSha256(macKey, dataToMac);
}); assert(equalConstTime(opts.mac, realMac), "Bad MAC");
return aes256CbcDecrypt(opts.iv, encryptionKey, opts.ciphertext);
});
}; };