Merge pull request #36 from NodeFactoryIo/mpetrunic/protobuf-gen

protobuf gen
This commit is contained in:
Belma Gutlic 2020-02-17 11:32:42 +01:00 committed by GitHub
commit 7b52edad94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 433 additions and 59 deletions

View File

@ -8,7 +8,9 @@
}
}
],
"@babel/preset-typescript"
["@babel/preset-typescript", {
"allowNamespaces": true
}]
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",

View File

@ -8,7 +8,9 @@
}
}
],
"@babel/preset-typescript"
["@babel/preset-typescript", {
"allowNamespaces": true
}]
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",

View File

@ -9,7 +9,9 @@
"modules": false
}
],
"@babel/preset-typescript"
["@babel/preset-typescript", {
"allowNamespaces": true
}]
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",

View File

@ -20,9 +20,10 @@
"scripts": {
"prebuild": "rm -rf lib && rm -rf dist",
"build": "yarn run build:node && yarn run build:web && yarn run build:types",
"build:node": "babel --config-file ./babel.config.json src --copy-files -x .ts -d dist --source-maps",
"build:web": "babel --config-file ./babel.web.config.json src --copy-files -x .ts -d lib --source-maps",
"build:node": "babel --no-babelrc --config-file ./babel.config.json src --copy-files -x .ts -d dist --source-maps",
"build:web": "babel --no-babelrc --config-file ./babel.web.config.json src --copy-files -x .ts -d lib --source-maps",
"build:types": "tsc --declaration --outDir dist --emitDeclarationOnly",
"proto:gen": "pbjs -t static-module -o ./src/proto/payload.js ./src/proto/payload.proto && pbts -o ./src/proto/payload.d.ts ./src/proto/payload.js && yarn run lint --fix",
"check-types": "tsc --incremental --noEmit",
"lint": "eslint --ext .ts src/",
"pretest": "yarn check-types",

106
src/proto/payload.d.ts vendored Normal file
View File

@ -0,0 +1,106 @@
import * as $protobuf from "protobufjs";
/** Namespace pb. */
export namespace pb {
/** Properties of a NoiseHandshakePayload. */
interface INoiseHandshakePayload {
/** NoiseHandshakePayload identityKey */
identityKey?: (Uint8Array|null);
/** NoiseHandshakePayload identitySig */
identitySig?: (Uint8Array|null);
/** NoiseHandshakePayload data */
data?: (Uint8Array|null);
}
/** Represents a NoiseHandshakePayload. */
class NoiseHandshakePayload implements INoiseHandshakePayload {
/**
* Constructs a new NoiseHandshakePayload.
* @param [properties] Properties to set
*/
constructor(properties?: pb.INoiseHandshakePayload);
/** NoiseHandshakePayload identityKey. */
public identityKey: Uint8Array;
/** NoiseHandshakePayload identitySig. */
public identitySig: Uint8Array;
/** NoiseHandshakePayload data. */
public data: Uint8Array;
/**
* Creates a new NoiseHandshakePayload instance using the specified properties.
* @param [properties] Properties to set
* @returns NoiseHandshakePayload instance
*/
public static create(properties?: pb.INoiseHandshakePayload): pb.NoiseHandshakePayload;
/**
* Encodes the specified NoiseHandshakePayload message. Does not implicitly {@link pb.NoiseHandshakePayload.verify|verify} messages.
* @param message NoiseHandshakePayload message or plain object to encode
* @param [writer] Writer to encode to
* @returns Writer
*/
public static encode(message: pb.INoiseHandshakePayload, writer?: $protobuf.Writer): $protobuf.Writer;
/**
* Encodes the specified NoiseHandshakePayload message, length delimited. Does not implicitly {@link pb.NoiseHandshakePayload.verify|verify} messages.
* @param message NoiseHandshakePayload message or plain object to encode
* @param [writer] Writer to encode to
* @returns Writer
*/
public static encodeDelimited(message: pb.INoiseHandshakePayload, writer?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a NoiseHandshakePayload message from the specified reader or buffer.
* @param reader Reader or buffer to decode from
* @param [length] Message length if known beforehand
* @returns NoiseHandshakePayload
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): pb.NoiseHandshakePayload;
/**
* Decodes a NoiseHandshakePayload message from the specified reader or buffer, length delimited.
* @param reader Reader or buffer to decode from
* @returns NoiseHandshakePayload
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): pb.NoiseHandshakePayload;
/**
* Verifies a NoiseHandshakePayload message.
* @param message Plain object to verify
* @returns `null` if valid, otherwise the reason why it is not
*/
public static verify(message: { [k: string]: any }): (string|null);
/**
* Creates a NoiseHandshakePayload message from a plain object. Also converts values to their respective internal types.
* @param object Plain object
* @returns NoiseHandshakePayload
*/
public static fromObject(object: { [k: string]: any }): pb.NoiseHandshakePayload;
/**
* Creates a plain object from a NoiseHandshakePayload message. Also converts values to other types if specified.
* @param message NoiseHandshakePayload
* @param [options] Conversion options
* @returns Plain object
*/
public static toObject(message: pb.NoiseHandshakePayload, options?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this NoiseHandshakePayload to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
}

291
src/proto/payload.js Normal file
View File

@ -0,0 +1,291 @@
/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
(function(global, factory) { /* global define, require, module */
/* AMD */ if (typeof define === 'function' && define.amd)
define(["protobufjs/minimal"], factory);
/* CommonJS */ else if (typeof require === 'function' && typeof module === 'object' && module && module.exports)
module.exports = factory(require("protobufjs/minimal"));
})(this, function($protobuf) {
"use strict";
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.pb = (function() {
/**
* Namespace pb.
* @exports pb
* @namespace
*/
var pb = {};
pb.NoiseHandshakePayload = (function() {
/**
* Properties of a NoiseHandshakePayload.
* @memberof pb
* @interface INoiseHandshakePayload
* @property {Uint8Array|null} [identityKey] NoiseHandshakePayload identityKey
* @property {Uint8Array|null} [identitySig] NoiseHandshakePayload identitySig
* @property {Uint8Array|null} [data] NoiseHandshakePayload data
*/
/**
* Constructs a new NoiseHandshakePayload.
* @memberof pb
* @classdesc Represents a NoiseHandshakePayload.
* @implements INoiseHandshakePayload
* @constructor
* @param {pb.INoiseHandshakePayload=} [properties] Properties to set
*/
function NoiseHandshakePayload(properties) {
if (properties)
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null)
this[keys[i]] = properties[keys[i]];
}
/**
* NoiseHandshakePayload identityKey.
* @member {Uint8Array} identityKey
* @memberof pb.NoiseHandshakePayload
* @instance
*/
NoiseHandshakePayload.prototype.identityKey = $util.newBuffer([]);
/**
* NoiseHandshakePayload identitySig.
* @member {Uint8Array} identitySig
* @memberof pb.NoiseHandshakePayload
* @instance
*/
NoiseHandshakePayload.prototype.identitySig = $util.newBuffer([]);
/**
* NoiseHandshakePayload data.
* @member {Uint8Array} data
* @memberof pb.NoiseHandshakePayload
* @instance
*/
NoiseHandshakePayload.prototype.data = $util.newBuffer([]);
/**
* Creates a new NoiseHandshakePayload instance using the specified properties.
* @function create
* @memberof pb.NoiseHandshakePayload
* @static
* @param {pb.INoiseHandshakePayload=} [properties] Properties to set
* @returns {pb.NoiseHandshakePayload} NoiseHandshakePayload instance
*/
NoiseHandshakePayload.create = function create(properties) {
return new NoiseHandshakePayload(properties);
};
/**
* Encodes the specified NoiseHandshakePayload message. Does not implicitly {@link pb.NoiseHandshakePayload.verify|verify} messages.
* @function encode
* @memberof pb.NoiseHandshakePayload
* @static
* @param {pb.INoiseHandshakePayload} message NoiseHandshakePayload message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
NoiseHandshakePayload.encode = function encode(message, writer) {
if (!writer)
writer = $Writer.create();
if (message.identityKey != null && message.hasOwnProperty("identityKey"))
writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.identityKey);
if (message.identitySig != null && message.hasOwnProperty("identitySig"))
writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.identitySig);
if (message.data != null && message.hasOwnProperty("data"))
writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.data);
return writer;
};
/**
* Encodes the specified NoiseHandshakePayload message, length delimited. Does not implicitly {@link pb.NoiseHandshakePayload.verify|verify} messages.
* @function encodeDelimited
* @memberof pb.NoiseHandshakePayload
* @static
* @param {pb.INoiseHandshakePayload} message NoiseHandshakePayload message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
NoiseHandshakePayload.encodeDelimited = function encodeDelimited(message, writer) {
return this.encode(message, writer).ldelim();
};
/**
* Decodes a NoiseHandshakePayload message from the specified reader or buffer.
* @function decode
* @memberof pb.NoiseHandshakePayload
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Message length if known beforehand
* @returns {pb.NoiseHandshakePayload} NoiseHandshakePayload
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
NoiseHandshakePayload.decode = function decode(reader, length) {
if (!(reader instanceof $Reader))
reader = $Reader.create(reader);
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.pb.NoiseHandshakePayload();
while (reader.pos < end) {
var tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.identityKey = reader.bytes();
break;
case 2:
message.identitySig = reader.bytes();
break;
case 3:
message.data = reader.bytes();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
};
/**
* Decodes a NoiseHandshakePayload message from the specified reader or buffer, length delimited.
* @function decodeDelimited
* @memberof pb.NoiseHandshakePayload
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {pb.NoiseHandshakePayload} NoiseHandshakePayload
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
NoiseHandshakePayload.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof $Reader))
reader = new $Reader(reader);
return this.decode(reader, reader.uint32());
};
/**
* Verifies a NoiseHandshakePayload message.
* @function verify
* @memberof pb.NoiseHandshakePayload
* @static
* @param {Object.<string,*>} message Plain object to verify
* @returns {string|null} `null` if valid, otherwise the reason why it is not
*/
NoiseHandshakePayload.verify = function verify(message) {
if (typeof message !== "object" || message === null)
return "object expected";
if (message.identityKey != null && message.hasOwnProperty("identityKey"))
if (!(message.identityKey && typeof message.identityKey.length === "number" || $util.isString(message.identityKey)))
return "identityKey: buffer expected";
if (message.identitySig != null && message.hasOwnProperty("identitySig"))
if (!(message.identitySig && typeof message.identitySig.length === "number" || $util.isString(message.identitySig)))
return "identitySig: buffer expected";
if (message.data != null && message.hasOwnProperty("data"))
if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data)))
return "data: buffer expected";
return null;
};
/**
* Creates a NoiseHandshakePayload message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof pb.NoiseHandshakePayload
* @static
* @param {Object.<string,*>} object Plain object
* @returns {pb.NoiseHandshakePayload} NoiseHandshakePayload
*/
NoiseHandshakePayload.fromObject = function fromObject(object) {
if (object instanceof $root.pb.NoiseHandshakePayload)
return object;
var message = new $root.pb.NoiseHandshakePayload();
if (object.identityKey != null)
if (typeof object.identityKey === "string")
$util.base64.decode(object.identityKey, message.identityKey = $util.newBuffer($util.base64.length(object.identityKey)), 0);
else if (object.identityKey.length)
message.identityKey = object.identityKey;
if (object.identitySig != null)
if (typeof object.identitySig === "string")
$util.base64.decode(object.identitySig, message.identitySig = $util.newBuffer($util.base64.length(object.identitySig)), 0);
else if (object.identitySig.length)
message.identitySig = object.identitySig;
if (object.data != null)
if (typeof object.data === "string")
$util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0);
else if (object.data.length)
message.data = object.data;
return message;
};
/**
* Creates a plain object from a NoiseHandshakePayload message. Also converts values to other types if specified.
* @function toObject
* @memberof pb.NoiseHandshakePayload
* @static
* @param {pb.NoiseHandshakePayload} message NoiseHandshakePayload
* @param {$protobuf.IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
*/
NoiseHandshakePayload.toObject = function toObject(message, options) {
if (!options)
options = {};
var object = {};
if (options.defaults) {
if (options.bytes === String)
object.identityKey = "";
else {
object.identityKey = [];
if (options.bytes !== Array)
object.identityKey = $util.newBuffer(object.identityKey);
}
if (options.bytes === String)
object.identitySig = "";
else {
object.identitySig = [];
if (options.bytes !== Array)
object.identitySig = $util.newBuffer(object.identitySig);
}
if (options.bytes === String)
object.data = "";
else {
object.data = [];
if (options.bytes !== Array)
object.data = $util.newBuffer(object.data);
}
}
if (message.identityKey != null && message.hasOwnProperty("identityKey"))
object.identityKey = options.bytes === String ? $util.base64.encode(message.identityKey, 0, message.identityKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.identityKey) : message.identityKey;
if (message.identitySig != null && message.hasOwnProperty("identitySig"))
object.identitySig = options.bytes === String ? $util.base64.encode(message.identitySig, 0, message.identitySig.length) : options.bytes === Array ? Array.prototype.slice.call(message.identitySig) : message.identitySig;
if (message.data != null && message.hasOwnProperty("data"))
object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data;
return object;
};
/**
* Converts this NoiseHandshakePayload to JSON.
* @function toJSON
* @memberof pb.NoiseHandshakePayload
* @instance
* @returns {Object.<string,*>} JSON object
*/
NoiseHandshakePayload.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return NoiseHandshakePayload;
})();
return pb;
})();
return $root;
});

View File

@ -1,20 +0,0 @@
{
"nested": {
"NoiseHandshakePayload": {
"fields": {
"identityKey": {
"type": "bytes",
"id": 1
},
"identitySig": {
"type": "bytes",
"id": 2
},
"data": {
"type": "bytes",
"id": 3
}
}
}
}
}

8
src/proto/payload.proto Normal file
View File

@ -0,0 +1,8 @@
syntax = "proto3";
package pb;
message NoiseHandshakePayload {
bytes identity_key = 1;
bytes identity_sig = 2;
bytes data = 3;
}

View File

@ -1,17 +1,13 @@
import { x25519, HKDF, SHA256 } from 'bcrypto';
import protobuf from "protobufjs";
import { Buffer } from "buffer";
import {HKDF, SHA256, x25519} from 'bcrypto';
import {Buffer} from "buffer";
import PeerId from "peer-id";
import * as crypto from 'libp2p-crypto';
import { KeyPair } from "./@types/libp2p";
import {KeyPair} from "./@types/libp2p";
import {bytes, bytes32} from "./@types/basic";
import {Hkdf, INoisePayload} from "./@types/handshake";
import payloadProto from "./proto/payload.json";
import {pb} from "./proto/payload";
async function loadPayloadProto () {
const payloadProtoBuf = await protobuf.Root.fromJSON(payloadProto);
return payloadProtoBuf.lookupType("NoiseHandshakePayload");
}
const NoiseHandshakePayloadProto = pb.NoiseHandshakePayload;
export function generateKeypair(): KeyPair {
const privateKey = x25519.privateKeyGenerate();
@ -43,19 +39,14 @@ export async function createHandshakePayload(
signedPayload: bytes,
earlyData?: bytes,
): Promise<bytes> {
const NoiseHandshakePayload = await loadPayloadProto();
const earlyDataPayload = earlyData ?
{
data: earlyData,
} : {};
const payloadInit = NoiseHandshakePayload.create({
const payloadInit = NoiseHandshakePayloadProto.create({
identityKey: libp2pPublicKey,
identitySig: signedPayload,
...earlyDataPayload,
data: earlyData || null,
});
return Buffer.from(NoiseHandshakePayload.encode(payloadInit).finish());
return Buffer.from(NoiseHandshakePayloadProto.encode(payloadInit).finish());
}
@ -63,14 +54,13 @@ export async function signPayload(peerId: PeerId, payload: bytes): Promise<bytes
return peerId.privKey.sign(payload);
}
export async function getPeerIdFromPayload(payload: INoisePayload): Promise<PeerId> {
return await PeerId.createFromPubKey(Buffer.from(payload.identityKey));
export async function getPeerIdFromPayload(payload: pb.INoiseHandshakePayload): Promise<PeerId> {
return await PeerId.createFromPubKey(Buffer.from(payload.identityKey as Uint8Array));
}
export async function decodePayload(payload: bytes): Promise<INoisePayload> {
const NoiseHandshakePayload = await loadPayloadProto();
return NoiseHandshakePayload.toObject(
NoiseHandshakePayload.decode(payload)
export async function decodePayload(payload: bytes): Promise<pb.INoiseHandshakePayload> {
return NoiseHandshakePayloadProto.toObject(
NoiseHandshakePayloadProto.decode(payload)
) as INoisePayload;
}
@ -92,19 +82,11 @@ async function isValidPeerId(peerId: bytes, publicKeyProtobuf: bytes) {
*/
export async function verifySignedPayload(
noiseStaticKey: bytes,
payload: INoisePayload,
payload: pb.INoiseHandshakePayload,
remotePeer: PeerId
): Promise<PeerId> {
try {
//temporary fix until protobufsjs conversion options starts working
//by default it ends up as Uint8Array
payload.identityKey = Buffer.from(payload.identityKey);
payload.identitySig = Buffer.from(payload.identitySig);
} catch (e) {
throw new Error("Failed to decode received payload. Reason: " + e.message);
}
if (!(await isValidPeerId(remotePeer.id, payload.identityKey)) ) {
if (!(await isValidPeerId(remotePeer.id, Buffer.from(payload.identityKey as Uint8Array)))) {
throw new Error("Peer ID doesn't match libp2p public key.");
}
@ -128,7 +110,7 @@ export function getHkdf(ck: bytes32, ikm: bytes): Hkdf {
const k2 = okm.slice(32, 64);
const k3 = okm.slice(64, 96);
return [ k1, k2, k3 ];
return [k1, k2, k3];
}
export function isValidPublicKey(pk: bytes): boolean {