@libp2p/peer-record 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +179 -0
  3. package/dist/src/envelope/envelope.d.ts +77 -0
  4. package/dist/src/envelope/envelope.js +241 -0
  5. package/dist/src/envelope/index.d.ts +47 -0
  6. package/dist/src/envelope/index.d.ts.map +1 -0
  7. package/dist/src/envelope/index.js +126 -0
  8. package/dist/src/envelope/index.js.map +1 -0
  9. package/dist/src/errors.d.ts +4 -0
  10. package/dist/src/errors.d.ts.map +1 -0
  11. package/dist/src/errors.js +4 -0
  12. package/dist/src/errors.js.map +1 -0
  13. package/dist/src/index.d.ts +3 -0
  14. package/dist/src/index.d.ts.map +1 -0
  15. package/dist/src/index.js +3 -0
  16. package/dist/src/index.js.map +1 -0
  17. package/dist/src/peer-record/consts.d.ts +3 -0
  18. package/dist/src/peer-record/consts.d.ts.map +1 -0
  19. package/dist/src/peer-record/consts.js +7 -0
  20. package/dist/src/peer-record/consts.js.map +1 -0
  21. package/dist/src/peer-record/index.d.ts +44 -0
  22. package/dist/src/peer-record/index.d.ts.map +1 -0
  23. package/dist/src/peer-record/index.js +71 -0
  24. package/dist/src/peer-record/index.js.map +1 -0
  25. package/dist/src/peer-record/peer-record.d.ts +133 -0
  26. package/dist/src/peer-record/peer-record.js +365 -0
  27. package/package.json +164 -0
  28. package/src/envelope/envelope.d.ts +77 -0
  29. package/src/envelope/envelope.js +241 -0
  30. package/src/envelope/envelope.proto +19 -0
  31. package/src/envelope/index.ts +159 -0
  32. package/src/errors.ts +4 -0
  33. package/src/index.ts +3 -0
  34. package/src/peer-record/consts.js +9 -0
  35. package/src/peer-record/index.ts +104 -0
  36. package/src/peer-record/peer-record.d.ts +133 -0
  37. package/src/peer-record/peer-record.js +365 -0
  38. package/src/peer-record/peer-record.proto +18 -0
package/package.json ADDED
@@ -0,0 +1,164 @@
1
+ {
2
+ "name": "@libp2p/peer-record",
3
+ "version": "0.0.0",
4
+ "description": "Used to transfer signed peer data across the network",
5
+ "license": "Apache-2.0 OR MIT",
6
+ "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-peer-record#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/libp2p/js-libp2p-interfaces/issues"
13
+ },
14
+ "keywords": [
15
+ "IPFS"
16
+ ],
17
+ "engines": {
18
+ "node": ">=16.0.0",
19
+ "npm": ">=7.0.0"
20
+ },
21
+ "type": "module",
22
+ "types": "./dist/src/index.d.ts",
23
+ "files": [
24
+ "src",
25
+ "dist/src",
26
+ "!dist/test",
27
+ "!**/*.tsbuildinfo"
28
+ ],
29
+ "exports": {
30
+ ".": {
31
+ "import": "./dist/src/index.js"
32
+ }
33
+ },
34
+ "eslintConfig": {
35
+ "extends": "ipfs",
36
+ "parserOptions": {
37
+ "sourceType": "module"
38
+ }
39
+ },
40
+ "release": {
41
+ "branches": [
42
+ "master"
43
+ ],
44
+ "plugins": [
45
+ [
46
+ "@semantic-release/commit-analyzer",
47
+ {
48
+ "preset": "conventionalcommits",
49
+ "releaseRules": [
50
+ {
51
+ "breaking": true,
52
+ "release": "major"
53
+ },
54
+ {
55
+ "revert": true,
56
+ "release": "patch"
57
+ },
58
+ {
59
+ "type": "feat",
60
+ "release": "minor"
61
+ },
62
+ {
63
+ "type": "fix",
64
+ "release": "patch"
65
+ },
66
+ {
67
+ "type": "chore",
68
+ "release": "patch"
69
+ },
70
+ {
71
+ "type": "docs",
72
+ "release": "patch"
73
+ },
74
+ {
75
+ "type": "test",
76
+ "release": "patch"
77
+ },
78
+ {
79
+ "scope": "no-release",
80
+ "release": false
81
+ }
82
+ ]
83
+ }
84
+ ],
85
+ [
86
+ "@semantic-release/release-notes-generator",
87
+ {
88
+ "preset": "conventionalcommits",
89
+ "presetConfig": {
90
+ "types": [
91
+ {
92
+ "type": "feat",
93
+ "section": "Features"
94
+ },
95
+ {
96
+ "type": "fix",
97
+ "section": "Bug Fixes"
98
+ },
99
+ {
100
+ "type": "chore",
101
+ "section": "Trivial Changes"
102
+ },
103
+ {
104
+ "type": "docs",
105
+ "section": "Trivial Changes"
106
+ },
107
+ {
108
+ "type": "test",
109
+ "section": "Tests"
110
+ }
111
+ ]
112
+ }
113
+ }
114
+ ],
115
+ "@semantic-release/changelog",
116
+ "@semantic-release/npm",
117
+ "@semantic-release/github",
118
+ "@semantic-release/git"
119
+ ]
120
+ },
121
+ "scripts": {
122
+ "lint": "aegir lint",
123
+ "dep-check": "aegir dep-check dist/src/**/*.js test/src/**/*.js",
124
+ "build": "tsc",
125
+ "postbuild": "npm run build:copy-proto-files",
126
+ "generate": "npm run generate:envelope && npm run generate:envelope-types && npm run generate:peer-record && npm run generate:peer-record-types",
127
+ "generate:envelope": "pbjs -t static-module -w es6 -r libp2p-peer-record-envelope --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/envelope/envelope.js ./src/envelope/envelope.proto",
128
+ "generate:envelope-types": "pbts -o src/envelope/envelope.d.ts src/envelope/envelope.js",
129
+ "generate:peer-record": "pbjs -t static-module -w es6 -r libp2p-peer-record --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/peer-record/peer-record.js ./src/peer-record/peer-record.proto",
130
+ "generate:peer-record-types": "pbts -o src/peer-record/peer-record.d.ts src/peer-record/peer-record.js",
131
+ "build:copy-proto-files": "cp src/envelope/envelope.js dist/src/envelope && cp src/envelope/*.d.ts dist/src/envelope && cp src/peer-record/peer-record.js dist/src/peer-record && cp src/peer-record/*.d.ts dist/src/peer-record",
132
+ "pretest": "npm run build",
133
+ "test": "aegir test -f ./dist/test",
134
+ "test:chrome": "npm run test -- -t browser",
135
+ "test:chrome-webworker": "npm run test -- -t webworker",
136
+ "test:firefox": "npm run test -- -t browser -- --browser firefox",
137
+ "test:firefox-webworker": "npm run test -- -t webworker -- --browser firefox",
138
+ "test:node": "npm run test -- -t node --cov",
139
+ "test:electron-main": "npm run test -- -t electron-main"
140
+ },
141
+ "dependencies": {
142
+ "@libp2p/interfaces": "^1.2.0",
143
+ "protobufjs": "^6.10.2",
144
+ "@libp2p/logger": "^1.0.1",
145
+ "interface-datastore": "^6.1.0",
146
+ "@multiformats/multiaddr": "^10.1.5",
147
+ "it-all": "^1.0.6",
148
+ "it-filter": "^1.0.3",
149
+ "it-pipe": "^2.0.3",
150
+ "it-map": "^1.0.6",
151
+ "it-foreach": "^0.1.1",
152
+ "multiformats": "^9.6.3",
153
+ "@libp2p/crypto": "^0.22.7",
154
+ "varint": "^6.0.0",
155
+ "@libp2p/utils": "^1.0.5"
156
+ },
157
+ "devDependencies": {
158
+ "@types/varint": "^6.0.0",
159
+ "aegir": "^36.1.3",
160
+ "sinon": "^13.0.1",
161
+ "@libp2p/peer-id-factory": "^1.0.3",
162
+ "@libp2p/interface-compliance-tests": "^1.0.8"
163
+ }
164
+ }
@@ -0,0 +1,77 @@
1
+ import * as $protobuf from "protobufjs";
2
+ /** Properties of an Envelope. */
3
+ export interface IEnvelope {
4
+
5
+ /** Envelope publicKey */
6
+ publicKey?: (Uint8Array|null);
7
+
8
+ /** Envelope payloadType */
9
+ payloadType?: (Uint8Array|null);
10
+
11
+ /** Envelope payload */
12
+ payload?: (Uint8Array|null);
13
+
14
+ /** Envelope signature */
15
+ signature?: (Uint8Array|null);
16
+ }
17
+
18
+ /** Represents an Envelope. */
19
+ export class Envelope implements IEnvelope {
20
+
21
+ /**
22
+ * Constructs a new Envelope.
23
+ * @param [p] Properties to set
24
+ */
25
+ constructor(p?: IEnvelope);
26
+
27
+ /** Envelope publicKey. */
28
+ public publicKey: Uint8Array;
29
+
30
+ /** Envelope payloadType. */
31
+ public payloadType: Uint8Array;
32
+
33
+ /** Envelope payload. */
34
+ public payload: Uint8Array;
35
+
36
+ /** Envelope signature. */
37
+ public signature: Uint8Array;
38
+
39
+ /**
40
+ * Encodes the specified Envelope message. Does not implicitly {@link Envelope.verify|verify} messages.
41
+ * @param m Envelope message or plain object to encode
42
+ * @param [w] Writer to encode to
43
+ * @returns Writer
44
+ */
45
+ public static encode(m: IEnvelope, w?: $protobuf.Writer): $protobuf.Writer;
46
+
47
+ /**
48
+ * Decodes an Envelope message from the specified reader or buffer.
49
+ * @param r Reader or buffer to decode from
50
+ * @param [l] Message length if known beforehand
51
+ * @returns Envelope
52
+ * @throws {Error} If the payload is not a reader or valid buffer
53
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
54
+ */
55
+ public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Envelope;
56
+
57
+ /**
58
+ * Creates an Envelope message from a plain object. Also converts values to their respective internal types.
59
+ * @param d Plain object
60
+ * @returns Envelope
61
+ */
62
+ public static fromObject(d: { [k: string]: any }): Envelope;
63
+
64
+ /**
65
+ * Creates a plain object from an Envelope message. Also converts values to other types if specified.
66
+ * @param m Envelope
67
+ * @param [o] Conversion options
68
+ * @returns Plain object
69
+ */
70
+ public static toObject(m: Envelope, o?: $protobuf.IConversionOptions): { [k: string]: any };
71
+
72
+ /**
73
+ * Converts this Envelope to JSON.
74
+ * @returns JSON object
75
+ */
76
+ public toJSON(): { [k: string]: any };
77
+ }
@@ -0,0 +1,241 @@
1
+ /*eslint-disable*/
2
+ import $protobuf from "protobufjs/minimal.js";
3
+
4
+ // Common aliases
5
+ const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
6
+
7
+ // Exported root namespace
8
+ const $root = $protobuf.roots["libp2p-peer-record-envelope"] || ($protobuf.roots["libp2p-peer-record-envelope"] = {});
9
+
10
+ export const Envelope = $root.Envelope = (() => {
11
+
12
+ /**
13
+ * Properties of an Envelope.
14
+ * @exports IEnvelope
15
+ * @interface IEnvelope
16
+ * @property {Uint8Array|null} [publicKey] Envelope publicKey
17
+ * @property {Uint8Array|null} [payloadType] Envelope payloadType
18
+ * @property {Uint8Array|null} [payload] Envelope payload
19
+ * @property {Uint8Array|null} [signature] Envelope signature
20
+ */
21
+
22
+ /**
23
+ * Constructs a new Envelope.
24
+ * @exports Envelope
25
+ * @classdesc Represents an Envelope.
26
+ * @implements IEnvelope
27
+ * @constructor
28
+ * @param {IEnvelope=} [p] Properties to set
29
+ */
30
+ function Envelope(p) {
31
+ if (p)
32
+ for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
33
+ if (p[ks[i]] != null)
34
+ this[ks[i]] = p[ks[i]];
35
+ }
36
+
37
+ /**
38
+ * Envelope publicKey.
39
+ * @member {Uint8Array} publicKey
40
+ * @memberof Envelope
41
+ * @instance
42
+ */
43
+ Envelope.prototype.publicKey = $util.newBuffer([]);
44
+
45
+ /**
46
+ * Envelope payloadType.
47
+ * @member {Uint8Array} payloadType
48
+ * @memberof Envelope
49
+ * @instance
50
+ */
51
+ Envelope.prototype.payloadType = $util.newBuffer([]);
52
+
53
+ /**
54
+ * Envelope payload.
55
+ * @member {Uint8Array} payload
56
+ * @memberof Envelope
57
+ * @instance
58
+ */
59
+ Envelope.prototype.payload = $util.newBuffer([]);
60
+
61
+ /**
62
+ * Envelope signature.
63
+ * @member {Uint8Array} signature
64
+ * @memberof Envelope
65
+ * @instance
66
+ */
67
+ Envelope.prototype.signature = $util.newBuffer([]);
68
+
69
+ /**
70
+ * Encodes the specified Envelope message. Does not implicitly {@link Envelope.verify|verify} messages.
71
+ * @function encode
72
+ * @memberof Envelope
73
+ * @static
74
+ * @param {IEnvelope} m Envelope message or plain object to encode
75
+ * @param {$protobuf.Writer} [w] Writer to encode to
76
+ * @returns {$protobuf.Writer} Writer
77
+ */
78
+ Envelope.encode = function encode(m, w) {
79
+ if (!w)
80
+ w = $Writer.create();
81
+ if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey"))
82
+ w.uint32(10).bytes(m.publicKey);
83
+ if (m.payloadType != null && Object.hasOwnProperty.call(m, "payloadType"))
84
+ w.uint32(18).bytes(m.payloadType);
85
+ if (m.payload != null && Object.hasOwnProperty.call(m, "payload"))
86
+ w.uint32(26).bytes(m.payload);
87
+ if (m.signature != null && Object.hasOwnProperty.call(m, "signature"))
88
+ w.uint32(42).bytes(m.signature);
89
+ return w;
90
+ };
91
+
92
+ /**
93
+ * Decodes an Envelope message from the specified reader or buffer.
94
+ * @function decode
95
+ * @memberof Envelope
96
+ * @static
97
+ * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
98
+ * @param {number} [l] Message length if known beforehand
99
+ * @returns {Envelope} Envelope
100
+ * @throws {Error} If the payload is not a reader or valid buffer
101
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
102
+ */
103
+ Envelope.decode = function decode(r, l) {
104
+ if (!(r instanceof $Reader))
105
+ r = $Reader.create(r);
106
+ var c = l === undefined ? r.len : r.pos + l, m = new $root.Envelope();
107
+ while (r.pos < c) {
108
+ var t = r.uint32();
109
+ switch (t >>> 3) {
110
+ case 1:
111
+ m.publicKey = r.bytes();
112
+ break;
113
+ case 2:
114
+ m.payloadType = r.bytes();
115
+ break;
116
+ case 3:
117
+ m.payload = r.bytes();
118
+ break;
119
+ case 5:
120
+ m.signature = r.bytes();
121
+ break;
122
+ default:
123
+ r.skipType(t & 7);
124
+ break;
125
+ }
126
+ }
127
+ return m;
128
+ };
129
+
130
+ /**
131
+ * Creates an Envelope message from a plain object. Also converts values to their respective internal types.
132
+ * @function fromObject
133
+ * @memberof Envelope
134
+ * @static
135
+ * @param {Object.<string,*>} d Plain object
136
+ * @returns {Envelope} Envelope
137
+ */
138
+ Envelope.fromObject = function fromObject(d) {
139
+ if (d instanceof $root.Envelope)
140
+ return d;
141
+ var m = new $root.Envelope();
142
+ if (d.publicKey != null) {
143
+ if (typeof d.publicKey === "string")
144
+ $util.base64.decode(d.publicKey, m.publicKey = $util.newBuffer($util.base64.length(d.publicKey)), 0);
145
+ else if (d.publicKey.length)
146
+ m.publicKey = d.publicKey;
147
+ }
148
+ if (d.payloadType != null) {
149
+ if (typeof d.payloadType === "string")
150
+ $util.base64.decode(d.payloadType, m.payloadType = $util.newBuffer($util.base64.length(d.payloadType)), 0);
151
+ else if (d.payloadType.length)
152
+ m.payloadType = d.payloadType;
153
+ }
154
+ if (d.payload != null) {
155
+ if (typeof d.payload === "string")
156
+ $util.base64.decode(d.payload, m.payload = $util.newBuffer($util.base64.length(d.payload)), 0);
157
+ else if (d.payload.length)
158
+ m.payload = d.payload;
159
+ }
160
+ if (d.signature != null) {
161
+ if (typeof d.signature === "string")
162
+ $util.base64.decode(d.signature, m.signature = $util.newBuffer($util.base64.length(d.signature)), 0);
163
+ else if (d.signature.length)
164
+ m.signature = d.signature;
165
+ }
166
+ return m;
167
+ };
168
+
169
+ /**
170
+ * Creates a plain object from an Envelope message. Also converts values to other types if specified.
171
+ * @function toObject
172
+ * @memberof Envelope
173
+ * @static
174
+ * @param {Envelope} m Envelope
175
+ * @param {$protobuf.IConversionOptions} [o] Conversion options
176
+ * @returns {Object.<string,*>} Plain object
177
+ */
178
+ Envelope.toObject = function toObject(m, o) {
179
+ if (!o)
180
+ o = {};
181
+ var d = {};
182
+ if (o.defaults) {
183
+ if (o.bytes === String)
184
+ d.publicKey = "";
185
+ else {
186
+ d.publicKey = [];
187
+ if (o.bytes !== Array)
188
+ d.publicKey = $util.newBuffer(d.publicKey);
189
+ }
190
+ if (o.bytes === String)
191
+ d.payloadType = "";
192
+ else {
193
+ d.payloadType = [];
194
+ if (o.bytes !== Array)
195
+ d.payloadType = $util.newBuffer(d.payloadType);
196
+ }
197
+ if (o.bytes === String)
198
+ d.payload = "";
199
+ else {
200
+ d.payload = [];
201
+ if (o.bytes !== Array)
202
+ d.payload = $util.newBuffer(d.payload);
203
+ }
204
+ if (o.bytes === String)
205
+ d.signature = "";
206
+ else {
207
+ d.signature = [];
208
+ if (o.bytes !== Array)
209
+ d.signature = $util.newBuffer(d.signature);
210
+ }
211
+ }
212
+ if (m.publicKey != null && m.hasOwnProperty("publicKey")) {
213
+ d.publicKey = o.bytes === String ? $util.base64.encode(m.publicKey, 0, m.publicKey.length) : o.bytes === Array ? Array.prototype.slice.call(m.publicKey) : m.publicKey;
214
+ }
215
+ if (m.payloadType != null && m.hasOwnProperty("payloadType")) {
216
+ d.payloadType = o.bytes === String ? $util.base64.encode(m.payloadType, 0, m.payloadType.length) : o.bytes === Array ? Array.prototype.slice.call(m.payloadType) : m.payloadType;
217
+ }
218
+ if (m.payload != null && m.hasOwnProperty("payload")) {
219
+ d.payload = o.bytes === String ? $util.base64.encode(m.payload, 0, m.payload.length) : o.bytes === Array ? Array.prototype.slice.call(m.payload) : m.payload;
220
+ }
221
+ if (m.signature != null && m.hasOwnProperty("signature")) {
222
+ d.signature = o.bytes === String ? $util.base64.encode(m.signature, 0, m.signature.length) : o.bytes === Array ? Array.prototype.slice.call(m.signature) : m.signature;
223
+ }
224
+ return d;
225
+ };
226
+
227
+ /**
228
+ * Converts this Envelope to JSON.
229
+ * @function toJSON
230
+ * @memberof Envelope
231
+ * @instance
232
+ * @returns {Object.<string,*>} JSON object
233
+ */
234
+ Envelope.prototype.toJSON = function toJSON() {
235
+ return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
236
+ };
237
+
238
+ return Envelope;
239
+ })();
240
+
241
+ export { $root as default };
@@ -0,0 +1,19 @@
1
+ syntax = "proto3";
2
+
3
+ message Envelope {
4
+ // public_key is the public key of the keypair the enclosed payload was
5
+ // signed with.
6
+ bytes public_key = 1;
7
+
8
+ // payload_type encodes the type of payload, so that it can be deserialized
9
+ // deterministically.
10
+ bytes payload_type = 2;
11
+
12
+ // payload is the actual payload carried inside this envelope.
13
+ bytes payload = 3;
14
+
15
+ // signature is the signature produced by the private key corresponding to
16
+ // the enclosed public key, over the payload, prefixing a domain string for
17
+ // additional security.
18
+ bytes signature = 5;
19
+ }
@@ -0,0 +1,159 @@
1
+ import errCode from 'err-code'
2
+ import { concat as uint8arraysConcat } from 'uint8arrays/concat'
3
+ import { fromString as uint8arraysFromString }from 'uint8arrays/from-string'
4
+ import { unmarshalPrivateKey, unmarshalPublicKey } from '@libp2p/crypto/keys'
5
+ import varint from 'varint'
6
+ import { equals as uint8arraysEquals } from 'uint8arrays/equals'
7
+ import { codes } from '../errors.js'
8
+ import { Envelope as Protobuf } from './envelope.js'
9
+ import { PeerId } from '@libp2p/peer-id'
10
+ import type { Record, Envelope } from '@libp2p/interfaces/record'
11
+
12
+ export interface EnvelopeOptions {
13
+ peerId: PeerId
14
+ payloadType: Uint8Array
15
+ payload: Uint8Array
16
+ signature: Uint8Array
17
+ }
18
+
19
+ export class RecordEnvelope implements Envelope {
20
+ /**
21
+ * Unmarshal a serialized Envelope protobuf message
22
+ */
23
+ static createFromProtobuf = async (data: Uint8Array) => {
24
+ const envelopeData = Protobuf.decode(data)
25
+ const peerId = await PeerId.fromKeys(envelopeData.publicKey)
26
+
27
+ return new RecordEnvelope({
28
+ peerId,
29
+ payloadType: envelopeData.payloadType,
30
+ payload: envelopeData.payload,
31
+ signature: envelopeData.signature
32
+ })
33
+ }
34
+
35
+ /**
36
+ * Seal marshals the given Record, places the marshaled bytes inside an Envelope
37
+ * and signs it with the given peerId's private key
38
+ */
39
+ static seal = async (record: Record, peerId: PeerId) => {
40
+ const domain = record.domain
41
+ const payloadType = record.codec
42
+ const payload = record.marshal()
43
+
44
+ const signData = formatSignaturePayload(domain, payloadType, payload)
45
+
46
+ if (peerId.privateKey == null) {
47
+ throw new Error('Missing private key')
48
+ }
49
+
50
+ const key = await unmarshalPrivateKey(peerId.privateKey)
51
+ const signature = await key.sign(signData)
52
+
53
+ return new RecordEnvelope({
54
+ peerId,
55
+ payloadType,
56
+ payload,
57
+ signature
58
+ })
59
+ }
60
+
61
+ /**
62
+ * Open and certify a given marshalled envelope.
63
+ * Data is unmarshalled and the signature validated for the given domain.
64
+ */
65
+ static openAndCertify = async (data: Uint8Array, domain: string) => {
66
+ const envelope = await RecordEnvelope.createFromProtobuf(data)
67
+ const valid = await envelope.validate(domain)
68
+
69
+ if (!valid) {
70
+ throw errCode(new Error('envelope signature is not valid for the given domain'), codes.ERR_SIGNATURE_NOT_VALID)
71
+ }
72
+
73
+ return envelope
74
+ }
75
+
76
+ public peerId: PeerId
77
+ public payloadType: Uint8Array
78
+ public payload: Uint8Array
79
+ public signature: Uint8Array
80
+ public marshaled?: Uint8Array
81
+
82
+ /**
83
+ * The Envelope is responsible for keeping an arbitrary signed record
84
+ * by a libp2p peer.
85
+ */
86
+ constructor (options: EnvelopeOptions) {
87
+ const { peerId, payloadType, payload, signature } = options
88
+
89
+ this.peerId = peerId
90
+ this.payloadType = payloadType
91
+ this.payload = payload
92
+ this.signature = signature
93
+ }
94
+
95
+ /**
96
+ * Marshal the envelope content
97
+ */
98
+ marshal () {
99
+ if (this.marshaled == null) {
100
+ this.marshaled = Protobuf.encode({
101
+ publicKey: this.peerId.publicKey,
102
+ payloadType: this.payloadType,
103
+ payload: this.payload,
104
+ signature: this.signature
105
+ }).finish()
106
+ }
107
+
108
+ return this.marshaled
109
+ }
110
+
111
+ /**
112
+ * Verifies if the other Envelope is identical to this one
113
+ */
114
+ equals (other: Envelope) {
115
+ return uint8arraysEquals(this.marshal(), other.marshal())
116
+ }
117
+
118
+ /**
119
+ * Validate envelope data signature for the given domain
120
+ */
121
+ validate (domain: string) {
122
+ const signData = formatSignaturePayload(domain, this.payloadType, this.payload)
123
+
124
+ if (this.peerId.publicKey == null) {
125
+ throw new Error('Missing public key')
126
+ }
127
+
128
+ const key = unmarshalPublicKey(this.peerId.publicKey)
129
+
130
+ return key.verify(signData, this.signature)
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Helper function that prepares a Uint8Array to sign or verify a signature
136
+ */
137
+ const formatSignaturePayload = (domain: string, payloadType: Uint8Array, payload: Uint8Array) => {
138
+ // When signing, a peer will prepare a Uint8Array by concatenating the following:
139
+ // - The length of the domain separation string string in bytes
140
+ // - The domain separation string, encoded as UTF-8
141
+ // - The length of the payload_type field in bytes
142
+ // - The value of the payload_type field
143
+ // - The length of the payload field in bytes
144
+ // - The value of the payload field
145
+
146
+ const domainUint8Array = uint8arraysFromString(domain)
147
+ const domainLength = varint.encode(domainUint8Array.byteLength)
148
+ const payloadTypeLength = varint.encode(payloadType.length)
149
+ const payloadLength = varint.encode(payload.length)
150
+
151
+ return uint8arraysConcat([
152
+ new Uint8Array(domainLength),
153
+ domainUint8Array,
154
+ new Uint8Array(payloadTypeLength),
155
+ payloadType,
156
+ new Uint8Array(payloadLength),
157
+ payload
158
+ ])
159
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,4 @@
1
+
2
+ export const codes = {
3
+ ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID'
4
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+
2
+ export { RecordEnvelope } from './envelope/index.js'
3
+ export { PeerRecord } from './peer-record/index.js'
@@ -0,0 +1,9 @@
1
+
2
+ // The domain string used for peer records contained in a Envelope.
3
+ export const ENVELOPE_DOMAIN_PEER_RECORD = 'libp2p-peer-record'
4
+
5
+ // The type hint used to identify peer records in a Envelope.
6
+ // Defined in https://github.com/multiformats/multicodec/blob/master/table.csv
7
+ // with name "libp2p-peer-record"
8
+ export const ENVELOPE_PAYLOAD_TYPE_PEER_RECORD = Uint8Array.from([3, 1])
9
+