@reallyme/codec 0.1.20 → 0.1.22

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.
@@ -1,8 +1,11 @@
1
1
  // SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2
2
  //
3
3
  // SPDX-License-Identifier: Apache-2.0
4
+ import { create } from "@bufbuild/protobuf";
4
5
  import { ReallyMeCodecError } from "./errors.js";
5
- import { ensureBytesInput, ensureStringInput, ensureStringValue, readBooleanOutput, readBytesOutput, readBytesProperty, readObjectOutput, readProtoResultOutput, readOptionalLengthProperty, readStringOutput, readStringProperty, } from "./readOutput.js";
6
+ import { CodecMulticodecLookupPrefixRequestSchema, CodecMulticodecPrefixForNameRequestSchema, CodecMulticodecTableRequestSchema, CodecMultikeyParseRequestSchema, CodecOperationRequestSchema, } from "./proto/generated/reallyme/codec/v1/codec_pb.js";
7
+ import { processGeneratedProtoRequest, protoPayloadOrThrow, } from "./protoProcess.js";
8
+ import { ensureBytesInput, ensureStringInput, ensureStringValue, readBooleanOutput, readBytesOutput, readBytesProperty, readObjectOutput, readOptionalLengthProperty, readStringOutput, readStringProperty, } from "./readOutput.js";
6
9
  import { requireReallyMeCodecWasmProvider } from "./wasmProvider.js";
7
10
  const validTags = new Set([
8
11
  "encryption",
@@ -17,6 +20,7 @@ const validKeyMaterialKinds = new Set([
17
20
  "private-key",
18
21
  "symmetric-key",
19
22
  ]);
23
+ const MAX_MULTICODEC_TABLE_ENTRIES = 1_024;
20
24
  const readTag = (object) => {
21
25
  const tag = readStringProperty(object, "tag");
22
26
  if (!validTags.has(tag)) {
@@ -77,10 +81,28 @@ const readParsedMultikey = (value) => {
77
81
  return { ...parsed, expectedPublicKeyLength };
78
82
  };
79
83
  const readMulticodecTable = (value) => {
80
- if (!Array.isArray(value)) {
84
+ try {
85
+ if (!Array.isArray(value) ||
86
+ Object.getPrototypeOf(value) !== Array.prototype ||
87
+ value.length > MAX_MULTICODEC_TABLE_ENTRIES) {
88
+ throw new ReallyMeCodecError("provider-failure");
89
+ }
90
+ const table = [];
91
+ for (let index = 0; index < value.length; index += 1) {
92
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
93
+ if (descriptor === undefined || !("value" in descriptor)) {
94
+ throw new ReallyMeCodecError("provider-failure");
95
+ }
96
+ table.push(readMulticodecMetadata(descriptor.value));
97
+ }
98
+ return table;
99
+ }
100
+ catch (error) {
101
+ if (error instanceof ReallyMeCodecError) {
102
+ throw error;
103
+ }
81
104
  throw new ReallyMeCodecError("provider-failure");
82
105
  }
83
- return value.map(readMulticodecMetadata);
84
106
  };
85
107
  export const base58btcEncode = (bytes) => {
86
108
  ensureBytesInput(bytes);
@@ -107,32 +129,49 @@ export const multicodecPrefixForName = (codecName) => {
107
129
  return readMulticodecMetadata(requireReallyMeCodecWasmProvider().multicodecPrefixForName(codecName));
108
130
  };
109
131
  export const multicodecPrefixForNameProto = (codecName) => {
110
- ensureStringInput(codecName);
111
- return readBytesOutput(requireReallyMeCodecWasmProvider().multicodecPrefixForNameProto(codecName));
132
+ return protoPayloadOrThrow(multicodecPrefixForNameProtoResult(codecName));
112
133
  };
113
134
  export const multicodecPrefixForNameProtoResult = (codecName) => {
114
135
  ensureStringInput(codecName);
115
- return readProtoResultOutput(requireReallyMeCodecWasmProvider().multicodecPrefixForNameProtoResult(codecName));
136
+ return processGeneratedProtoRequest(create(CodecOperationRequestSchema, {
137
+ operation: {
138
+ case: "multicodecPrefixForName",
139
+ value: create(CodecMulticodecPrefixForNameRequestSchema, {
140
+ name: codecName,
141
+ }),
142
+ },
143
+ }));
116
144
  };
117
145
  export const multicodecLookupPrefix = (bytes) => {
118
146
  ensureBytesInput(bytes);
119
147
  return readMulticodecMetadata(requireReallyMeCodecWasmProvider().multicodecLookupPrefix(bytes));
120
148
  };
121
149
  export const multicodecLookupPrefixProto = (bytes) => {
122
- ensureBytesInput(bytes);
123
- return readBytesOutput(requireReallyMeCodecWasmProvider().multicodecLookupPrefixProto(bytes));
150
+ return protoPayloadOrThrow(multicodecLookupPrefixProtoResult(bytes));
124
151
  };
125
152
  export const multicodecLookupPrefixProtoResult = (bytes) => {
126
153
  ensureBytesInput(bytes);
127
- return readProtoResultOutput(requireReallyMeCodecWasmProvider().multicodecLookupPrefixProtoResult(bytes));
154
+ return processGeneratedProtoRequest(create(CodecOperationRequestSchema, {
155
+ operation: {
156
+ case: "multicodecLookupPrefix",
157
+ value: create(CodecMulticodecLookupPrefixRequestSchema, {
158
+ value: bytes,
159
+ }),
160
+ },
161
+ }));
128
162
  };
129
163
  export const multicodecStripPrefix = (bytes) => {
130
164
  ensureBytesInput(bytes);
131
165
  return readBytesOutput(requireReallyMeCodecWasmProvider().multicodecStripPrefix(bytes));
132
166
  };
133
167
  export const multicodecTable = () => readMulticodecTable(requireReallyMeCodecWasmProvider().multicodecTable());
134
- export const multicodecTableProto = () => readBytesOutput(requireReallyMeCodecWasmProvider().multicodecTableProto());
135
- export const multicodecTableProtoResult = () => readProtoResultOutput(requireReallyMeCodecWasmProvider().multicodecTableProtoResult());
168
+ export const multicodecTableProto = () => protoPayloadOrThrow(multicodecTableProtoResult());
169
+ export const multicodecTableProtoResult = () => processGeneratedProtoRequest(create(CodecOperationRequestSchema, {
170
+ operation: {
171
+ case: "multicodecTable",
172
+ value: create(CodecMulticodecTableRequestSchema),
173
+ },
174
+ }));
136
175
  export const multikeyEncode = (codecName, publicKey) => {
137
176
  ensureStringInput(codecName);
138
177
  ensureBytesInput(publicKey);
@@ -143,12 +182,16 @@ export const multikeyParse = (multikey) => {
143
182
  return readParsedMultikey(requireReallyMeCodecWasmProvider().multikeyParse(multikey));
144
183
  };
145
184
  export const multikeyParseProto = (multikey) => {
146
- ensureStringInput(multikey);
147
- return readBytesOutput(requireReallyMeCodecWasmProvider().multikeyParseProto(multikey));
185
+ return protoPayloadOrThrow(multikeyParseProtoResult(multikey));
148
186
  };
149
187
  export const multikeyParseProtoResult = (multikey) => {
150
188
  ensureStringInput(multikey);
151
- return readProtoResultOutput(requireReallyMeCodecWasmProvider().multikeyParseProtoResult(multikey));
189
+ return processGeneratedProtoRequest(create(CodecOperationRequestSchema, {
190
+ operation: {
191
+ case: "multikeyParse",
192
+ value: create(CodecMultikeyParseRequestSchema, { multikey }),
193
+ },
194
+ }));
152
195
  };
153
196
  export const bindingTypeMatchesCodec = (bindingType, codecName) => {
154
197
  ensureStringInput(bindingType);
package/dist/pem.d.ts CHANGED
@@ -15,7 +15,7 @@ export type ReallyMePemDocument = Readonly<{
15
15
  label: ReallyMePemLabel;
16
16
  der: Uint8Array;
17
17
  }>;
18
- export declare const decodePem: (input: string, policy?: ReallyMePemDecodePolicy) => ReallyMePemDocument;
19
- export declare const decodePemProto: (input: string, policy?: ReallyMePemDecodePolicy) => Uint8Array;
20
- export declare const decodePemProtoResult: (input: string, policy?: ReallyMePemDecodePolicy) => ReallyMeCodecProtoResult;
21
- export declare const encodePem: (label: ReallyMePemLabel, der: Uint8Array, options?: ReallyMePemEncodeOptions) => string;
18
+ export declare const decodePem: (input: Uint8Array, policy?: ReallyMePemDecodePolicy) => ReallyMePemDocument;
19
+ export declare const decodePemProto: (input: Uint8Array, policy?: ReallyMePemDecodePolicy) => Uint8Array;
20
+ export declare const decodePemProtoResult: (input: Uint8Array, policy?: ReallyMePemDecodePolicy) => ReallyMeCodecProtoResult;
21
+ export declare const encodePem: (label: ReallyMePemLabel, der: Uint8Array, options?: ReallyMePemEncodeOptions) => Uint8Array;
package/dist/pem.js CHANGED
@@ -1,14 +1,29 @@
1
1
  // SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2
2
  //
3
3
  // SPDX-License-Identifier: Apache-2.0
4
+ import { create } from "@bufbuild/protobuf";
5
+ import { stringifyBoundaryJson } from "./boundary.js";
4
6
  import { ReallyMeCodecError } from "./errors.js";
5
- import { ensureBytesInput, ensureStringInput, readBytesOutput, readBytesProperty, readObjectOutput, readProtoResultOutput, readStringOutput, readStringProperty, } from "./readOutput.js";
7
+ import { CodecOperationRequestSchema, CodecPemDecodeOptionsSchema, CodecPemDecodeRequestSchema, CodecPemLabel, } from "./proto/generated/reallyme/codec/v1/codec_pb.js";
8
+ import { processGeneratedProtoRequest, protoPayloadOrThrow, } from "./protoProcess.js";
9
+ import { ensureBytesInput, readBytesOutput, readBytesProperty, readObjectOutput, readStringProperty, } from "./readOutput.js";
6
10
  import { requireReallyMeCodecWasmProvider } from "./wasmProvider.js";
7
11
  const validLabels = new Set([
8
12
  "PRIVATE KEY",
9
13
  "EC PRIVATE KEY",
10
14
  "PUBLIC KEY",
11
15
  ]);
16
+ const MAX_PEM_ALLOWED_LABELS = 1_024;
17
+ const pemDecodePolicyFields = new Set([
18
+ "allowedLabels",
19
+ "maxInputLen",
20
+ "maxDerLen",
21
+ ]);
22
+ const pemEncodeOptionFields = new Set([
23
+ "maxDerLen",
24
+ "lineWidth",
25
+ "lineEnding",
26
+ ]);
12
27
  const requirePemLabel = (label) => {
13
28
  if (!validLabels.has(label)) {
14
29
  throw new ReallyMeCodecError("invalid-input");
@@ -22,67 +37,199 @@ const requirePemLabel = (label) => {
22
37
  throw new ReallyMeCodecError("invalid-input");
23
38
  }
24
39
  };
40
+ const readPemLabel = (label) => {
41
+ if (!validLabels.has(label)) {
42
+ throw new ReallyMeCodecError("provider-failure");
43
+ }
44
+ switch (label) {
45
+ case "PRIVATE KEY":
46
+ case "EC PRIVATE KEY":
47
+ case "PUBLIC KEY":
48
+ return label;
49
+ default:
50
+ throw new ReallyMeCodecError("provider-failure");
51
+ }
52
+ };
25
53
  const requirePositiveInteger = (value) => {
26
54
  if (value !== undefined &&
27
55
  (!Number.isSafeInteger(value) || value <= 0)) {
28
56
  throw new ReallyMeCodecError("invalid-input");
29
57
  }
30
58
  };
59
+ const readSnapshotProperty = (value, name) => {
60
+ const descriptor = Object.getOwnPropertyDescriptor(value, name);
61
+ if (descriptor === undefined) {
62
+ return undefined;
63
+ }
64
+ if (!("value" in descriptor)) {
65
+ throw new ReallyMeCodecError("invalid-input");
66
+ }
67
+ return descriptor.value;
68
+ };
69
+ const snapshotOptionsRecord = (value, allowedFields) => {
70
+ try {
71
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
72
+ throw new ReallyMeCodecError("invalid-input");
73
+ }
74
+ const prototype = Object.getPrototypeOf(value);
75
+ if (prototype !== Object.prototype && prototype !== null) {
76
+ throw new ReallyMeCodecError("invalid-input");
77
+ }
78
+ const entries = [];
79
+ for (const key of Reflect.ownKeys(value)) {
80
+ if (typeof key !== "string" || !allowedFields.has(key)) {
81
+ throw new ReallyMeCodecError("invalid-input");
82
+ }
83
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
84
+ if (descriptor === undefined || !("value" in descriptor)) {
85
+ throw new ReallyMeCodecError("invalid-input");
86
+ }
87
+ entries.push([key, descriptor.value]);
88
+ }
89
+ return Object.fromEntries(entries);
90
+ }
91
+ catch (error) {
92
+ if (error instanceof ReallyMeCodecError) {
93
+ throw error;
94
+ }
95
+ throw new ReallyMeCodecError("invalid-input");
96
+ }
97
+ };
98
+ const readPositiveIntegerOption = (value, name) => {
99
+ const property = readSnapshotProperty(value, name);
100
+ if (property === undefined) {
101
+ return undefined;
102
+ }
103
+ if (typeof property !== "number") {
104
+ throw new ReallyMeCodecError("invalid-input");
105
+ }
106
+ requirePositiveInteger(property);
107
+ return property;
108
+ };
109
+ const snapshotDecodePolicy = (policy) => {
110
+ if (policy === undefined) {
111
+ return undefined;
112
+ }
113
+ const snapshot = snapshotOptionsRecord(policy, pemDecodePolicyFields);
114
+ const labelsValue = readSnapshotProperty(snapshot, "allowedLabels");
115
+ let allowedLabels;
116
+ if (labelsValue !== undefined) {
117
+ if (!Array.isArray(labelsValue) ||
118
+ Object.getPrototypeOf(labelsValue) !== Array.prototype ||
119
+ labelsValue.length > MAX_PEM_ALLOWED_LABELS) {
120
+ throw new ReallyMeCodecError("invalid-input");
121
+ }
122
+ allowedLabels = [];
123
+ for (let index = 0; index < labelsValue.length; index += 1) {
124
+ const label = readSnapshotProperty(labelsValue, String(index));
125
+ if (typeof label !== "string") {
126
+ throw new ReallyMeCodecError("invalid-input");
127
+ }
128
+ allowedLabels.push(requirePemLabel(label));
129
+ }
130
+ }
131
+ const maxInputLen = readPositiveIntegerOption(snapshot, "maxInputLen");
132
+ const maxDerLen = readPositiveIntegerOption(snapshot, "maxDerLen");
133
+ return {
134
+ ...(allowedLabels === undefined ? {} : { allowedLabels }),
135
+ ...(maxInputLen === undefined ? {} : { maxInputLen }),
136
+ ...(maxDerLen === undefined ? {} : { maxDerLen }),
137
+ };
138
+ };
139
+ const snapshotEncodeOptions = (options) => {
140
+ if (options === undefined) {
141
+ return undefined;
142
+ }
143
+ const snapshot = snapshotOptionsRecord(options, pemEncodeOptionFields);
144
+ const maxDerLen = readPositiveIntegerOption(snapshot, "maxDerLen");
145
+ const lineWidth = readPositiveIntegerOption(snapshot, "lineWidth");
146
+ const lineEndingValue = readSnapshotProperty(snapshot, "lineEnding");
147
+ let lineEnding;
148
+ if (lineEndingValue !== undefined) {
149
+ if (lineEndingValue !== "lf" && lineEndingValue !== "crlf") {
150
+ throw new ReallyMeCodecError("invalid-input");
151
+ }
152
+ lineEnding = lineEndingValue;
153
+ }
154
+ return {
155
+ ...(maxDerLen === undefined ? {} : { maxDerLen }),
156
+ ...(lineWidth === undefined ? {} : { lineWidth }),
157
+ ...(lineEnding === undefined ? {} : { lineEnding }),
158
+ };
159
+ };
160
+ const requireProtoUint32 = (value) => {
161
+ requirePositiveInteger(value);
162
+ if (value === undefined) {
163
+ return 0;
164
+ }
165
+ if (value > 0xffff_ffff) {
166
+ throw new ReallyMeCodecError("invalid-input");
167
+ }
168
+ return value;
169
+ };
170
+ const protoPemLabel = (label) => {
171
+ switch (label) {
172
+ case "PRIVATE KEY":
173
+ return CodecPemLabel.PRIVATE_KEY;
174
+ case "EC PRIVATE KEY":
175
+ return CodecPemLabel.EC_PRIVATE_KEY;
176
+ case "PUBLIC KEY":
177
+ return CodecPemLabel.PUBLIC_KEY;
178
+ }
179
+ };
31
180
  const encodeOptions = (options) => {
32
181
  if (options === undefined) {
33
182
  return "";
34
183
  }
35
- return JSON.stringify(options);
184
+ return stringifyBoundaryJson(options);
36
185
  };
37
186
  const readPemDocument = (value) => {
38
187
  const object = readObjectOutput(value);
39
188
  return {
40
- label: requirePemLabel(readStringProperty(object, "label")),
189
+ label: readPemLabel(readStringProperty(object, "label")),
41
190
  der: readBytesProperty(object, "der"),
42
191
  };
43
192
  };
44
193
  export const decodePem = (input, policy) => {
45
- ensureStringInput(input);
46
- if (policy?.allowedLabels !== undefined) {
47
- for (const label of policy.allowedLabels) {
48
- requirePemLabel(label);
49
- }
50
- }
51
- requirePositiveInteger(policy?.maxInputLen);
52
- requirePositiveInteger(policy?.maxDerLen);
53
- return readPemDocument(requireReallyMeCodecWasmProvider().pemDecode(input, encodeOptions(policy)));
194
+ ensureBytesInput(input);
195
+ const snapshot = snapshotDecodePolicy(policy);
196
+ return readPemDocument(requireReallyMeCodecWasmProvider().pemDecode(input, encodeOptions(snapshot)));
54
197
  };
55
198
  export const decodePemProto = (input, policy) => {
56
- ensureStringInput(input);
57
- if (policy?.allowedLabels !== undefined) {
58
- for (const label of policy.allowedLabels) {
59
- requirePemLabel(label);
60
- }
61
- }
62
- requirePositiveInteger(policy?.maxInputLen);
63
- requirePositiveInteger(policy?.maxDerLen);
64
- return readBytesOutput(requireReallyMeCodecWasmProvider().pemDecodeProto(input, encodeOptions(policy)));
199
+ return protoPayloadOrThrow(decodePemProtoResult(input, policy));
65
200
  };
66
201
  export const decodePemProtoResult = (input, policy) => {
67
- ensureStringInput(input);
68
- if (policy?.allowedLabels !== undefined) {
69
- for (const label of policy.allowedLabels) {
70
- requirePemLabel(label);
202
+ ensureBytesInput(input);
203
+ const snapshot = snapshotDecodePolicy(policy);
204
+ const allowedLabels = [];
205
+ if (snapshot?.allowedLabels !== undefined) {
206
+ for (const label of snapshot.allowedLabels) {
207
+ allowedLabels.push(protoPemLabel(requirePemLabel(label)));
208
+ }
209
+ }
210
+ const request = create(CodecPemDecodeRequestSchema, { pem: input });
211
+ try {
212
+ if (snapshot !== undefined) {
213
+ request.options = create(CodecPemDecodeOptionsSchema, {
214
+ allowedLabels,
215
+ maxInputLen: requireProtoUint32(snapshot.maxInputLen),
216
+ maxDerLen: requireProtoUint32(snapshot.maxDerLen),
217
+ });
71
218
  }
219
+ return processGeneratedProtoRequest(create(CodecOperationRequestSchema, {
220
+ operation: {
221
+ case: "pemDecode",
222
+ value: request,
223
+ },
224
+ }));
225
+ }
226
+ finally {
227
+ request.pem = new Uint8Array(0);
72
228
  }
73
- requirePositiveInteger(policy?.maxInputLen);
74
- requirePositiveInteger(policy?.maxDerLen);
75
- return readProtoResultOutput(requireReallyMeCodecWasmProvider().pemDecodeProtoResult(input, encodeOptions(policy)));
76
229
  };
77
230
  export const encodePem = (label, der, options) => {
78
231
  requirePemLabel(label);
79
232
  ensureBytesInput(der);
80
- requirePositiveInteger(options?.maxDerLen);
81
- requirePositiveInteger(options?.lineWidth);
82
- if (options?.lineEnding !== undefined &&
83
- options.lineEnding !== "lf" &&
84
- options.lineEnding !== "crlf") {
85
- throw new ReallyMeCodecError("invalid-input");
86
- }
87
- return readStringOutput(requireReallyMeCodecWasmProvider().pemEncode(label, der, encodeOptions(options)));
233
+ const snapshot = snapshotEncodeOptions(options);
234
+ return readBytesOutput(requireReallyMeCodecWasmProvider().pemEncode(label, der, encodeOptions(snapshot)));
88
235
  };