@reallyme/codec 0.1.21 → 0.2.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.
- package/NOTICE +16 -0
- package/README.md +55 -4
- package/dist/boundary.d.ts +17 -0
- package/dist/boundary.js +277 -0
- package/dist/cbor.d.ts +67 -4
- package/dist/cbor.js +1252 -66
- package/dist/deterministicCborBoundary.d.ts +11 -0
- package/dist/deterministicCborBoundary.js +17 -0
- package/dist/index.d.ts +39 -22
- package/dist/index.js +14 -18
- package/dist/jcs.js +3 -60
- package/dist/multiformat.d.ts +10 -12
- package/dist/multiformat.js +155 -91
- package/dist/operationContract.d.ts +31 -0
- package/dist/operationContract.js +754 -0
- package/dist/pem.d.ts +2 -5
- package/dist/pem.js +265 -41
- package/dist/proto/generated/reallyme/codec/v1/codec_pb.d.ts +906 -13
- package/dist/proto/generated/reallyme/codec/v1/codec_pb.js +278 -23
- package/dist/proto.d.ts +2 -2
- package/dist/proto.js +1 -1
- package/dist/readOutput.d.ts +8 -7
- package/dist/readOutput.js +136 -22
- package/dist/wasm/reallyme_codec_wasm.d.ts +25 -140
- package/dist/wasm/reallyme_codec_wasm.js +134 -428
- package/dist/wasm/reallyme_codec_wasm_bg.wasm +0 -0
- package/dist/wasmProvider.d.ts +5 -31
- package/dist/wasmProvider.js +18 -51
- package/package.json +4 -1
package/dist/pem.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ReallyMeCodecProtoResult } from "./readOutput.js";
|
|
2
1
|
export type ReallyMePemLabel = "PRIVATE KEY" | "EC PRIVATE KEY" | "PUBLIC KEY";
|
|
3
2
|
export type ReallyMePemLineEnding = "lf" | "crlf";
|
|
4
3
|
export type ReallyMePemDecodePolicy = Readonly<{
|
|
@@ -15,7 +14,5 @@ export type ReallyMePemDocument = Readonly<{
|
|
|
15
14
|
label: ReallyMePemLabel;
|
|
16
15
|
der: Uint8Array;
|
|
17
16
|
}>;
|
|
18
|
-
export declare const decodePem: (input:
|
|
19
|
-
export declare const
|
|
20
|
-
export declare const decodePemProtoResult: (input: string, policy?: ReallyMePemDecodePolicy) => ReallyMeCodecProtoResult;
|
|
21
|
-
export declare const encodePem: (label: ReallyMePemLabel, der: Uint8Array, options?: ReallyMePemEncodeOptions) => string;
|
|
17
|
+
export declare const decodePem: (input: Uint8Array, policy?: ReallyMePemDecodePolicy) => ReallyMePemDocument;
|
|
18
|
+
export declare const encodePem: (label: ReallyMePemLabel, der: Uint8Array, options?: ReallyMePemEncodeOptions) => Uint8Array;
|
package/dist/pem.js
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
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 {
|
|
6
|
-
import {
|
|
6
|
+
import { CodecOperationRequestSchema, CodecPemDecodeOptionsSchema, CodecPemDecodeRequestSchema, CodecPemEncodeOptionsSchema, CodecPemEncodeRequestSchema, CodecPemLabel, CodecPemLineEnding, } from "./proto/generated/reallyme/codec/v1/codec_pb.js";
|
|
7
|
+
import { clearGeneratedOperationResult, processGeneratedOperationRequest, } from "./operationContract.js";
|
|
8
|
+
import { ensureBytesInput, snapshotBoundedBytesInput, } from "./readOutput.js";
|
|
7
9
|
const validLabels = new Set([
|
|
8
10
|
"PRIVATE KEY",
|
|
9
11
|
"EC PRIVATE KEY",
|
|
10
12
|
"PUBLIC KEY",
|
|
11
13
|
]);
|
|
14
|
+
const MAX_PEM_ALLOWED_LABELS = 1_024;
|
|
15
|
+
const pemDecodePolicyFields = new Set([
|
|
16
|
+
"allowedLabels",
|
|
17
|
+
"maxInputLen",
|
|
18
|
+
"maxDerLen",
|
|
19
|
+
]);
|
|
20
|
+
const pemEncodeOptionFields = new Set([
|
|
21
|
+
"maxDerLen",
|
|
22
|
+
"lineWidth",
|
|
23
|
+
"lineEnding",
|
|
24
|
+
]);
|
|
12
25
|
const requirePemLabel = (label) => {
|
|
13
26
|
if (!validLabels.has(label)) {
|
|
14
27
|
throw new ReallyMeCodecError("invalid-input");
|
|
@@ -22,67 +35,278 @@ const requirePemLabel = (label) => {
|
|
|
22
35
|
throw new ReallyMeCodecError("invalid-input");
|
|
23
36
|
}
|
|
24
37
|
};
|
|
38
|
+
const readPemLabel = (label) => {
|
|
39
|
+
if (!validLabels.has(label)) {
|
|
40
|
+
throw new ReallyMeCodecError("provider-failure");
|
|
41
|
+
}
|
|
42
|
+
switch (label) {
|
|
43
|
+
case "PRIVATE KEY":
|
|
44
|
+
case "EC PRIVATE KEY":
|
|
45
|
+
case "PUBLIC KEY":
|
|
46
|
+
return label;
|
|
47
|
+
default:
|
|
48
|
+
throw new ReallyMeCodecError("provider-failure");
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const requireNoProviderUnknownFields = (message) => {
|
|
52
|
+
if (message.$unknown !== undefined && message.$unknown.length !== 0) {
|
|
53
|
+
throw new ReallyMeCodecError("provider-failure");
|
|
54
|
+
}
|
|
55
|
+
};
|
|
25
56
|
const requirePositiveInteger = (value) => {
|
|
26
57
|
if (value !== undefined &&
|
|
27
58
|
(!Number.isSafeInteger(value) || value <= 0)) {
|
|
28
59
|
throw new ReallyMeCodecError("invalid-input");
|
|
29
60
|
}
|
|
30
61
|
};
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
62
|
+
const readSnapshotProperty = (value, name) => {
|
|
63
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
64
|
+
if (descriptor === undefined) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
if (!("value" in descriptor)) {
|
|
68
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
69
|
+
}
|
|
70
|
+
return descriptor.value;
|
|
71
|
+
};
|
|
72
|
+
const snapshotOptionsRecord = (value, allowedFields) => {
|
|
73
|
+
try {
|
|
74
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
75
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
76
|
+
}
|
|
77
|
+
const prototype = Object.getPrototypeOf(value);
|
|
78
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
79
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
80
|
+
}
|
|
81
|
+
const entries = [];
|
|
82
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
83
|
+
if (typeof key !== "string" || !allowedFields.has(key)) {
|
|
84
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
85
|
+
}
|
|
86
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
87
|
+
if (descriptor === undefined || !("value" in descriptor)) {
|
|
88
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
89
|
+
}
|
|
90
|
+
entries.push([key, descriptor.value]);
|
|
91
|
+
}
|
|
92
|
+
return Object.fromEntries(entries);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof ReallyMeCodecError) {
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const readPositiveIntegerOption = (value, name) => {
|
|
102
|
+
const property = readSnapshotProperty(value, name);
|
|
103
|
+
if (property === undefined) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
if (typeof property !== "number") {
|
|
107
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
108
|
+
}
|
|
109
|
+
requirePositiveInteger(property);
|
|
110
|
+
return property;
|
|
111
|
+
};
|
|
112
|
+
const snapshotDecodePolicy = (policy) => {
|
|
113
|
+
if (policy === undefined) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
const snapshot = snapshotOptionsRecord(policy, pemDecodePolicyFields);
|
|
117
|
+
const labelsValue = readSnapshotProperty(snapshot, "allowedLabels");
|
|
118
|
+
let allowedLabels;
|
|
119
|
+
if (labelsValue !== undefined) {
|
|
120
|
+
if (!Array.isArray(labelsValue) ||
|
|
121
|
+
Object.getPrototypeOf(labelsValue) !== Array.prototype ||
|
|
122
|
+
labelsValue.length > MAX_PEM_ALLOWED_LABELS) {
|
|
123
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
124
|
+
}
|
|
125
|
+
allowedLabels = [];
|
|
126
|
+
for (let index = 0; index < labelsValue.length; index += 1) {
|
|
127
|
+
const label = readSnapshotProperty(labelsValue, String(index));
|
|
128
|
+
if (typeof label !== "string") {
|
|
129
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
130
|
+
}
|
|
131
|
+
allowedLabels.push(requirePemLabel(label));
|
|
132
|
+
}
|
|
34
133
|
}
|
|
35
|
-
|
|
134
|
+
const maxInputLen = readPositiveIntegerOption(snapshot, "maxInputLen");
|
|
135
|
+
const maxDerLen = readPositiveIntegerOption(snapshot, "maxDerLen");
|
|
136
|
+
return {
|
|
137
|
+
...(allowedLabels === undefined ? {} : { allowedLabels }),
|
|
138
|
+
...(maxInputLen === undefined ? {} : { maxInputLen }),
|
|
139
|
+
...(maxDerLen === undefined ? {} : { maxDerLen }),
|
|
140
|
+
};
|
|
36
141
|
};
|
|
37
|
-
const
|
|
38
|
-
|
|
142
|
+
const snapshotEncodeOptions = (options) => {
|
|
143
|
+
if (options === undefined) {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
const snapshot = snapshotOptionsRecord(options, pemEncodeOptionFields);
|
|
147
|
+
const maxDerLen = readPositiveIntegerOption(snapshot, "maxDerLen");
|
|
148
|
+
const lineWidth = readPositiveIntegerOption(snapshot, "lineWidth");
|
|
149
|
+
const lineEndingValue = readSnapshotProperty(snapshot, "lineEnding");
|
|
150
|
+
let lineEnding;
|
|
151
|
+
if (lineEndingValue !== undefined) {
|
|
152
|
+
if (lineEndingValue !== "lf" && lineEndingValue !== "crlf") {
|
|
153
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
154
|
+
}
|
|
155
|
+
lineEnding = lineEndingValue;
|
|
156
|
+
}
|
|
39
157
|
return {
|
|
40
|
-
|
|
41
|
-
|
|
158
|
+
...(maxDerLen === undefined ? {} : { maxDerLen }),
|
|
159
|
+
...(lineWidth === undefined ? {} : { lineWidth }),
|
|
160
|
+
...(lineEnding === undefined ? {} : { lineEnding }),
|
|
42
161
|
};
|
|
43
162
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
163
|
+
const requireProtoUint32 = (value) => {
|
|
164
|
+
requirePositiveInteger(value);
|
|
165
|
+
if (value === undefined) {
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
if (value > 0xffff_ffff) {
|
|
169
|
+
throw new ReallyMeCodecError("invalid-input");
|
|
170
|
+
}
|
|
171
|
+
return value;
|
|
172
|
+
};
|
|
173
|
+
const protoPemLabel = (label) => {
|
|
174
|
+
switch (label) {
|
|
175
|
+
case "PRIVATE KEY":
|
|
176
|
+
return CodecPemLabel.PRIVATE_KEY;
|
|
177
|
+
case "EC PRIVATE KEY":
|
|
178
|
+
return CodecPemLabel.EC_PRIVATE_KEY;
|
|
179
|
+
case "PUBLIC KEY":
|
|
180
|
+
return CodecPemLabel.PUBLIC_KEY;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const readPemDocument = (result) => {
|
|
184
|
+
try {
|
|
185
|
+
requireNoProviderUnknownFields(result);
|
|
186
|
+
return {
|
|
187
|
+
label: readPemLabel(result.label),
|
|
188
|
+
der: result.der.slice(),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
if (error instanceof ReallyMeCodecError) {
|
|
193
|
+
throw error;
|
|
49
194
|
}
|
|
195
|
+
throw new ReallyMeCodecError("provider-failure");
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
result.der.fill(0);
|
|
50
199
|
}
|
|
51
|
-
requirePositiveInteger(policy?.maxInputLen);
|
|
52
|
-
requirePositiveInteger(policy?.maxDerLen);
|
|
53
|
-
return readPemDocument(requireReallyMeCodecWasmProvider().pemDecode(input, encodeOptions(policy)));
|
|
54
200
|
};
|
|
55
|
-
export const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
201
|
+
export const decodePem = (input, policy) => {
|
|
202
|
+
ensureBytesInput(input);
|
|
203
|
+
const request = pemDecodeRequest(input, policy);
|
|
204
|
+
try {
|
|
205
|
+
const operationResult = processGeneratedOperationRequest(request);
|
|
206
|
+
if (operationResult.result.case !== "pemDecode") {
|
|
207
|
+
clearGeneratedOperationResult(operationResult);
|
|
208
|
+
throw new ReallyMeCodecError("provider-failure");
|
|
60
209
|
}
|
|
210
|
+
return readPemDocument(operationResult.result.value);
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
clearPemDecodeRequest(request);
|
|
61
214
|
}
|
|
62
|
-
requirePositiveInteger(policy?.maxInputLen);
|
|
63
|
-
requirePositiveInteger(policy?.maxDerLen);
|
|
64
|
-
return readBytesOutput(requireReallyMeCodecWasmProvider().pemDecodeProto(input, encodeOptions(policy)));
|
|
65
215
|
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
216
|
+
const pemDecodeRequest = (input, policy) => {
|
|
217
|
+
ensureBytesInput(input);
|
|
218
|
+
const snapshot = snapshotDecodePolicy(policy);
|
|
219
|
+
const allowedLabels = [];
|
|
220
|
+
if (snapshot?.allowedLabels !== undefined) {
|
|
221
|
+
for (const label of snapshot.allowedLabels) {
|
|
222
|
+
allowedLabels.push(protoPemLabel(requirePemLabel(label)));
|
|
71
223
|
}
|
|
72
224
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
225
|
+
const options = snapshot === undefined
|
|
226
|
+
? undefined
|
|
227
|
+
: create(CodecPemDecodeOptionsSchema, {
|
|
228
|
+
allowedLabels,
|
|
229
|
+
maxInputLen: requireProtoUint32(snapshot.maxInputLen),
|
|
230
|
+
maxDerLen: requireProtoUint32(snapshot.maxDerLen),
|
|
231
|
+
});
|
|
232
|
+
const pemSnapshot = snapshotBoundedBytesInput(input);
|
|
233
|
+
try {
|
|
234
|
+
const request = create(CodecPemDecodeRequestSchema, { pem: pemSnapshot });
|
|
235
|
+
if (options !== undefined) {
|
|
236
|
+
request.options = options;
|
|
237
|
+
}
|
|
238
|
+
return create(CodecOperationRequestSchema, {
|
|
239
|
+
operation: {
|
|
240
|
+
case: "pemDecode",
|
|
241
|
+
value: request,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
pemSnapshot.fill(0);
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const clearPemDecodeRequest = (request) => {
|
|
251
|
+
if (request.operation.case === "pemDecode") {
|
|
252
|
+
request.operation.value.pem.fill(0);
|
|
253
|
+
request.operation.value.pem = new Uint8Array(0);
|
|
254
|
+
}
|
|
76
255
|
};
|
|
77
256
|
export const encodePem = (label, der, options) => {
|
|
78
257
|
requirePemLabel(label);
|
|
79
258
|
ensureBytesInput(der);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
259
|
+
const snapshot = snapshotEncodeOptions(options);
|
|
260
|
+
const protoOptions = snapshot === undefined
|
|
261
|
+
? undefined
|
|
262
|
+
: create(CodecPemEncodeOptionsSchema, {
|
|
263
|
+
maxDerLen: requireProtoUint32(snapshot.maxDerLen),
|
|
264
|
+
lineWidth: requireProtoUint32(snapshot.lineWidth),
|
|
265
|
+
lineEnding: snapshot.lineEnding === "crlf"
|
|
266
|
+
? CodecPemLineEnding.CRLF
|
|
267
|
+
: snapshot.lineEnding === "lf"
|
|
268
|
+
? CodecPemLineEnding.LF
|
|
269
|
+
: CodecPemLineEnding.UNSPECIFIED,
|
|
270
|
+
});
|
|
271
|
+
const derSnapshot = snapshotBoundedBytesInput(der);
|
|
272
|
+
let request;
|
|
273
|
+
let operationRequest;
|
|
274
|
+
try {
|
|
275
|
+
request = create(CodecPemEncodeRequestSchema, {
|
|
276
|
+
label: protoPemLabel(label),
|
|
277
|
+
der: derSnapshot,
|
|
278
|
+
});
|
|
279
|
+
if (protoOptions !== undefined) {
|
|
280
|
+
request.options = protoOptions;
|
|
281
|
+
}
|
|
282
|
+
operationRequest = create(CodecOperationRequestSchema, {
|
|
283
|
+
operation: {
|
|
284
|
+
case: "pemEncode",
|
|
285
|
+
value: request,
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
derSnapshot.fill(0);
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
const operationResult = processGeneratedOperationRequest(operationRequest);
|
|
295
|
+
if (operationResult.result.case !== "pemEncode") {
|
|
296
|
+
clearGeneratedOperationResult(operationResult);
|
|
297
|
+
throw new ReallyMeCodecError("provider-failure");
|
|
298
|
+
}
|
|
299
|
+
const result = operationResult.result.value;
|
|
300
|
+
try {
|
|
301
|
+
requireNoProviderUnknownFields(result);
|
|
302
|
+
return result.pem.slice();
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
result.pem.fill(0);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
finally {
|
|
309
|
+
request.der.fill(0);
|
|
310
|
+
request.der = new Uint8Array(0);
|
|
86
311
|
}
|
|
87
|
-
return readStringOutput(requireReallyMeCodecWasmProvider().pemEncode(label, der, encodeOptions(options)));
|
|
88
312
|
};
|